<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Axelar Developer Blog]]></title><description><![CDATA[Explore the Axelar Developer Blog for the latest on cross-chain development. From tutorials to updates, our posts empower developers with the tools and knowledg]]></description><link>https://blog.axelar.dev</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1707854328394/hdHQ0wDJX.png</url><title>Axelar Developer Blog</title><link>https://blog.axelar.dev</link></image><generator>RSS for Node</generator><lastBuildDate>Wed, 15 Apr 2026 10:17:34 GMT</lastBuildDate><atom:link href="https://blog.axelar.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[ITS Hub Release Note: Everything You Need to Know]]></title><description><![CDATA[Release Date: January 2025
Status: Live on Mainnet
We’re thrilled to announce the launch of ITS Hub, a significant leap forward in blockchain interoperability. ITS Hub builds on the foundation of the Interchain Token Service (ITS) by introducing a ce...]]></description><link>https://blog.axelar.dev/its-hub-release-note-everything-you-need-to-know</link><guid isPermaLink="true">https://blog.axelar.dev/its-hub-release-note-everything-you-need-to-know</guid><category><![CDATA[axelar]]></category><category><![CDATA[InterchainToken]]></category><category><![CDATA[Web3]]></category><category><![CDATA[Blockchain]]></category><category><![CDATA[Smart Contracts]]></category><category><![CDATA[cosmwasm]]></category><category><![CDATA[Solana]]></category><category><![CDATA[Sui]]></category><category><![CDATA[Stellar]]></category><category><![CDATA[flow]]></category><category><![CDATA[Ethereum]]></category><dc:creator><![CDATA[Idris Olubisi]]></dc:creator><pubDate>Fri, 24 Jan 2025 15:37:04 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/Z41fl12z5zs/upload/6c3163d6561a18d25138eab9d58e4bd1.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><strong>Release Date:</strong> January 2025</p>
<p><strong>Status:</strong> <a target="_blank" href="https://github.com/axelarnetwork/axelar-amplifier/releases/tag/interchain-token-service-v1.0.0">Live on Mainnet</a></p>
<p>We’re thrilled to announce the launch of <a target="_blank" href="https://docs.axelar.dev/dev/amplifier/its-hub/introduction/"><strong>ITS Hub</strong></a>, a significant leap forward in blockchain interoperability. ITS Hub builds on the foundation of the <a target="_blank" href="https://docs.axelar.dev/dev/send-tokens/interchain-tokens/intro/">Interchain Token Service (ITS)</a> by introducing a central hub for <a target="_blank" href="https://docs.axelar.dev/dev/amplifier/its-hub/routing-mechanics/">routing</a> token operations, improved security, scalability, and interoperability across a diverse range of chains, including EVM and non-smart contract ecosystems.</p>
<h2 id="heading-its-hub-contract">ITS Hub Contract</h2>
<ul>
<li><p>✨ CosmWasm-based contract on the Axelar network</p>
</li>
<li><p>🔐 Central routing hub for token transfers</p>
</li>
<li><p>🌉 Supports both Amplifier and consensus chains</p>
</li>
<li><p>🔄 Replaces peer-to-peer token transfer structure</p>
</li>
</ul>
<h2 id="heading-token-support">Token Support</h2>
<ul>
<li><p><strong>ITS Tokens</strong>: Supported (with limitations)</p>
<ul>
<li><p>Based on General Message Passing (GMP)</p>
</li>
<li><p>Minted, burned, and managed connected EVM chains</p>
</li>
</ul>
</li>
<li><p><strong>Gateway Tokens:</strong> Not supported (future release)</p>
</li>
</ul>
<h2 id="heading-what-is-its-hub">What is ITS Hub?</h2>
<p>ITS Hub is a CosmWasm-based <a target="_blank" href="https://github.com/axelarnetwork/axelar-amplifier/tree/feat/its-hub/interchain-token-service">contract</a> on the Axelar network that serves as a central routing hub for all token transfers across <a target="_blank" href="https://docs.axelar.dev/dev/amplifier/introduction/">Amplifier</a> , consensus chains, and non-EVM chains like Sui and Stellar. This model replaces the peer-to-peer token transfer structure of the original ITS, enabling centralized balance tracking, rate limits, and streamlined security measures. By routing through ITS Hub, developers can bridge tokens while benefiting from enhanced interoperability across various blockchain ecosystems.</p>
<h2 id="heading-key-features-and-benefits">Key Features and Benefits</h2>
<ul>
<li><p><strong>Unified Token Routing</strong></p>
<p>  All ITS-enabled chains route token transactions through the ITS Hub, enabling simplified bridging for diverse blockchain architectures, including <a target="_blank" href="https://docs.axelar.dev/resources/contract-addresses/mainnet/#evm-contract-addresses">EVM</a> chains and non-smart contract chains like XRPL.</p>
</li>
<li><p><strong>Enhanced Security</strong></p>
<p>  ITS Hub applies centralized balance tracking to prevent over-escrow and enforce invariants, while rate limits mitigate risks from compromised chains or contracts.</p>
</li>
<li><p><strong>Scalability and Interoperability</strong></p>
<p>  ITS Hub supports ITS tokens, enabling seamless bridging across Amplifier chains, consensus chains, and non-smart contract ecosystems.</p>
</li>
<li><p><strong>Future Compatibility</strong></p>
<p>  ITS Hub is designed to accommodate evolving features such as integrating GMP Express, Axelar, and Cosmos chains and permissionless EVM onboarding support.</p>
</li>
<li><p><strong>Support for ITS Tokens</strong></p>
<p>  ITS tokens, based on Axelar’s General Message Passing (GMP), are minted, burned, and managed directly on connected EVM chains. Gateway tokens, however, are not supported in this iteration of ITS Hub.</p>
</li>
</ul>
<h2 id="heading-how-its-hub-works">How ITS Hub Works</h2>
<p>ITS Hub introduces a <strong>dual GMP call</strong> mechanism for routing token transactions:</p>
<ol>
<li><p><strong>Source Chain to ITS Hub</strong>: The <a target="_blank" href="https://etherscan.io/address/0xB5FB4BE02232B1bBA4dC8f81dc24C26980dE9e3C#code">ITS Edge Contract</a> sends a GMP call to the ITS Hub, wrapping the original payload.</p>
</li>
<li><p><strong>ITS Hub to Destination Chain</strong>: The ITS Hub processes the payload, applies security measures, and forwards it to the ITS Edge Contract on the destination chain.</p>
</li>
</ol>
<p>This design ensures robust state tracking and scalability across diverse chain architectures.</p>
<h2 id="heading-rollout-and-compatibility">Rollout and Compatibility</h2>
<p>ITS Hub supports <strong>Ethereum</strong>, <strong>Flow</strong>, and <strong>Sui for its initial release</strong>, with ongoing efforts to integrate <strong>Stellar</strong>, <strong>Ripple</strong>, <strong>Solana</strong>, and others. Amplifier chains currently support token transfers to Ethereum and other Amplifier chains, with broader functionality planned for future iterations.</p>
<blockquote>
<p>⚠️⚠️⚠️</p>
<ul>
<li><p>Custom ITS tokens are not supported in the current version.</p>
</li>
<li><p>Transfers from Amplifier chains are currently limited to Ethereum and other Amplifier chains.</p>
</li>
<li><p>Gateway Tokens integration is planned for future releases.</p>
</li>
</ul>
</blockquote>
<h2 id="heading-upcoming-chain-support">Upcoming Chain Support</h2>
<ul>
<li><p>Stellar</p>
</li>
<li><p>Ripple ("XRPL")</p>
</li>
<li><p>Solana</p>
</li>
<li><p>XRPL EVM sidechain</p>
</li>
<li><p>Hyperledger</p>
</li>
</ul>
<h2 id="heading-migration">Migration</h2>
<p>The ITS Hub architecture is designed for seamless integration with existing systems while preparing for future enhancements. Current ITS users can continue using the peer-to-peer system, with migration paths being developed for routing through ITS Hub in future updates.</p>
<h2 id="heading-whats-next">What’s Next?</h2>
<p>As Axelar continues to expand its ecosystem, ITS Hub will play a pivotal role in cross-chain interactions. Upcoming features include:</p>
<ul>
<li><p>Broader blockchain support for Amplifier and non-smart contract chains.</p>
</li>
<li><p>Integration with GMP Express for faster message passing.</p>
</li>
<li><p>Migration tools for existing P2P ITS connections to adopt ITS Hub.</p>
</li>
</ul>
<h2 id="heading-resources-and-documentation">Resources and Documentation</h2>
<ul>
<li><p><a target="_blank" href="https://docs.axelar.dev/dev/amplifier/its-hub/introduction/">ITS Hub Documentation</a></p>
</li>
<li><p><a target="_blank" href="https://docs.axelar.dev/dev/send-tokens/interchain-tokens/intro/">Interchain Token Service</a></p>
</li>
<li><p><a target="_blank" href="https://docs.axelar.dev/dev/general-message-passing/overview/">General Message Passing (GMP) Overview</a></p>
</li>
<li><p><a target="_blank" href="https://github.com/axelarnetwork/axelar-amplifier">Axelar Amplifier</a></p>
</li>
</ul>
<p>If you have any questions or need assistance, please open an issue in our <a target="_blank" href="https://github.com/axelarnetwork/axelar-support"><strong>support repository</strong></a>. We're here to help!</p>
]]></content:encoded></item><item><title><![CDATA[2024 Axelar Developer Highlights and Updates]]></title><description><![CDATA[In 2024, Axelar took massive strides toward making true multichain interoperability a reality. From unlocking new design spaces for builders to connecting more than 69 chains to unveiling the Mobius Development Stack. 2024 proved that Axelar is here ...]]></description><link>https://blog.axelar.dev/2024-axelar-developer-highlights-and-updates</link><guid isPermaLink="true">https://blog.axelar.dev/2024-axelar-developer-highlights-and-updates</guid><category><![CDATA[axelar]]></category><category><![CDATA[Developer]]></category><category><![CDATA[yearinreview]]></category><category><![CDATA[Web3]]></category><category><![CDATA[Blockchain]]></category><category><![CDATA[Cross-chain]]></category><category><![CDATA[Hedera]]></category><dc:creator><![CDATA[Idris Olubisi]]></dc:creator><pubDate>Tue, 24 Dec 2024 00:11:15 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1734711252065/aa42aba5-95ee-41f2-84db-b28182c83167.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In 2024, <a target="_blank" href="https://www.axelar.network/">Axelar</a> took massive strides toward making true multichain interoperability a reality. From unlocking new design spaces for builders to connecting more than 69 chains to unveiling the <a target="_blank" href="https://docs.axelar.dev/dev/what-is-mobius-development-stack/">Mobius Development Stack</a>. 2024 proved that Axelar is here to stitch the fragmented blockchain world into one cohesive network.</p>
<p><img src="https://cdn.prod.website-files.com/65f28017eaba8cd1f912fa9f/66fe97f66e44cd91c3477e5b_MobiusBanner.png" alt /></p>
<p>As the year began, there was a focus on bridging Web3 gaming and staking solutions, laying out roadmaps for the months ahead. By December (this year), significant mainnet milestones were celebrated, groundbreaking stack components were introduced, integration with leading ecosystems was achieved, and a thriving developer community was witnessed. Let’s look back at a transformative year.</p>
<h3 id="heading-tldr">TLDR</h3>
<ul>
<li><p>In 2024, Axelar advanced multichain interoperability, connecting over 69 chains.</p>
</li>
<li><p>Launched the <a target="_blank" href="https://docs.axelar.dev/dev/what-is-mobius-development-stack/">Mobius Development Stack</a>, enhancing blockchain connectivity.</p>
</li>
<li><p>Integrated with the <a target="_blank" href="https://www.immutable.com/">Immutable</a> ecosystem and enabled <a target="_blank" href="https://help.lido.fi/en/articles/9739043-bridging-wsteth-to-bnb-chain">Liquid Staked ETH</a> transfers to <a target="_blank" href="https://www.bnbchain.org/">BNB Chain</a>.</p>
</li>
<li><p>Introduced <a target="_blank" href="https://docs.axelar.dev/dev/send-tokens/interchain-tokens/intro/">Interchain Token Service (ITS)</a> and the <a target="_blank" href="https://docs.axelar.dev/dev/amplifier/introduction/">Interchain Amplifier</a>.</p>
</li>
<li><p>Launched the Axelar <a target="_blank" href="https://docs.axelar.dev">developer blog</a>.</p>
</li>
<li><p>Enhanced developer tools and community engagement through <a target="_blank" href="https://www.youtube.com/@axelar-network/streams">workshops</a> and <a target="_blank" href="https://blog.axelar.dev/">educational content</a>.</p>
</li>
<li><p>Surpassed <a target="_blank" href="https://axelarscan.io/">2 million cross-chain transactions</a>.</p>
</li>
<li><p>Integrated <a target="_blank" href="https://flow.com/">Flow</a> and <a target="_blank" href="https://hedera.com/">Hedera</a> with the Interchain Amplifier.</p>
</li>
<li><p>Sponsored events like <a target="_blank" href="https://ethglobal.com/showcase/">ETHGlobal Bangkok</a> and hosted <a target="_blank" href="https://www.youtube.com/watch?v=xPRLQFnJun4">Amplify Bangkok</a>, showcasing innovative projects.</p>
</li>
</ul>
<p>In January, integration with <a target="_blank" href="https://www.immutable.com/">Immutable</a> was achieved, enabling <a target="_blank" href="https://www.axelar.network/blog/lido-cross-chain-steth-with-axelar">Liquid Staked ETH (wstETH)</a> transfers to the BNB Chain while unveiling a roadmap featuring the Axelar Virtual Machine, Interchain Amplifier, and Interchain Tokens. Axelar was also announced as a partner to integrate with the Monad blockhain. February saw the launch of the Interchain Token Service on the mainnet, allowing the creation and registration of multichain tokens. By March, Axelar introduced the Interchain Amplifier concept, using CosmWasm and other innovations to build a chain-agnostic, decentralized cross-chain infrastructure.</p>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXfPXEyY9iObT2t4OdiWsbwC49-LNUDPANI8mnCOHx1Gg26AFpEFVHFqU9a24MHwczML2z3zTYntn-TLZj7ZRhBdCiSqQaD3SIMRXtlw4Fcz_49DK5knGwdOInT2pHrMEMX5xrm52Lv_bCgX6sjMq-z7U1gD?key=f2JTc6yq9nCJTFjiIDx2YQ" alt /></p>
<h3 id="heading-major-developments">Major Developments</h3>
<ul>
<li><p>Launched <a target="_blank" href="https://interchain.axelar.dev/">Interchain Token Service (ITS)</a> on mainnet (February).</p>
</li>
<li><p>Established a partnership with <a target="_blank" href="https://www.axelar.network/blog/immutable-selects-axelar-for-canonical-bridge-to-ethereum">Immutable for multichain GameFi</a>.</p>
</li>
<li><p>Established a <a target="_blank" href="https://x.com/monad_xyz/status/1752376222024446184">partnership</a> with <a target="_blank" href="https://www.monad.xyz/">Monad</a>.</p>
</li>
<li><p>Integrated with Lido DAO, bringing <a target="_blank" href="https://www.axelar.network/blog/lido-dao-approves-axelar-and-wormhole-to-bring-wsteth-to-bnb-chain">wstETH to BNB Chain</a>.</p>
</li>
<li><p>Released <a target="_blank" href="https://www.axelar.network/blog/roadmap-2024-jan">2024 roadmap</a> outlining ambitious platform expansion.</p>
</li>
</ul>
<h3 id="heading-technical-updates">Technical Updates</h3>
<ul>
<li><p>Released <a target="_blank" href="https://docs.axelar.dev/dev/send-tokens/interchain-tokens/intro/">comprehensive guides</a> for Interchain Token Service.</p>
</li>
<li><p>Enhanced <a target="_blank" href="https://github.com/axelarnetwork/axelarjs-sdk/releases">AxelarJS</a> capabilities for gas services and debugging.</p>
</li>
<li><p>Expanded developer documentation and <a target="_blank" href="https://docs.axelar.dev">tutorials</a>.</p>
</li>
<li><p>Integration with <a target="_blank" href="https://docs.moralis.com/web3-data-api/evm/integrations/Axelar/build-dapp-with-axelar-part-1">Moralis</a> was introduced to enhance development tools.</p>
</li>
</ul>
<h3 id="heading-community-engagement">Community Engagement</h3>
<ul>
<li><p>Participated in <a target="_blank" href="https://www.innovate.thetie.io/agenda#:~:text=5%3A00%2D5%3A30%20p.m.%20%7C%20Going%20Cross%2DChain">ETH Denver Hacker House</a>.</p>
</li>
<li><p>Conducted multiple <a target="_blank" href="https://www.youtube.com/@axelar-network/streams">developer workshops</a>.</p>
</li>
<li><p>Launched new <a target="_blank" href="https://www.youtube.com/@axelar-network/videos">developer-focused educational content</a>.</p>
</li>
<li><p>Launched the <a target="_blank" href="https://blog.axelar.dev">Developer Blog</a></p>
</li>
</ul>
<h2 id="heading-q2-april-june">Q2 (April - June)</h2>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXdNsjsgvrGdNzKTO6b2mMd9B5THEzwwsZHKZdC2WhqviW2YHKXIuqgi_yl97p4yhMAAMCZsXEq9BN3nFbnYskcNk0xySddgZRuCBqcJ9QgwrxzLFaKTKYOn84HaHzuzgukw8pW2AxnGpQMil3-yyUIQ2Iwe?key=XCSf4PhWoY6AfqAzTUnqwQ" alt /></p>
<p>The second quarter marked significant progress in Axelar's technical infrastructure and developer tools. During Q2, Axelar accelerated its efforts toward seamless, permissionless interoperability. In April, the Interchain Amplifier was released on <a target="_blank" href="https://devnet-amplifier.axelarscan.io">Devnet</a>, featuring chain-agnostic message routing and CosmWasm integrations. In May, the <a target="_blank" href="https://www.axelar.network/blog/celestia-rollkit-interoperability">Amplifier integrated with Rollkit</a>, supporting sovereign blockchains and leading to a more developer-focused content strategy.</p>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXewqFFghSE06aPrUQ_W8g16B1qTL_WejYjB0YiNLxed4ePhTuScHFK_MbfffWiLnJj6yyyc4Y_uWswtodr15Ia3LXGSA2B1aNdygR5RCvuuGCID2MiIUTpzekXjWLUf_36Gq3oq0QA1oqwwD3mgmN-bPI0?key=1DtaLT9Tswd5pnHJvv96Jg" alt /></p>
<p>By June, tutorials on building <a target="_blank" href="https://www.youtube.com/live/P0FDD5n1CJo?si=rX47WT1wL4QkX5AL">multichain stablecoins</a> were published, the <a target="_blank" href="https://docs.axelar.dev/dev/gas-service/intro/">Axelar Gas Service documentation</a> was updated, and <a target="_blank" href="https://github.com/axelarnetwork/foundry-axelar-gmp-example">Foundry Axelar gmp example</a> developer tools were improved with local testing support, fostering adoption and a strong technical ecosystem.</p>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXdQEoBJVq14Ldq0T4Cb7YTZHWcwPp0e5BOWR9E48eKOwZtjaiLIqWr6qP0H0FelEoCDNPfxF5gMJcrPJzclszdBpqjlgoY52w3rdR3hbS7LPpLE141EAkmhbPusYzhqOitkOOiGIq8wVkNue7SevyrcvVdS?key=9EL9oPbbyIK7KIFZfrvJJw" alt /></p>
<h3 id="heading-major-developments-1">Major Developments</h3>
<ul>
<li><p>Deployed <a target="_blank" href="https://docs.axelar.dev/dev/amplifier/introduction/">Interchain Amplifier on devnet</a>.</p>
</li>
<li><p>Enhanced <a target="_blank" href="https://github.com/ethereum/remix-workshops/tree/master/Interoperability">Remix (LearnETH) integration</a> with multichain development tutorials.</p>
</li>
<li><p>Expanded <a target="_blank" href="https://blog.axelar.dev/axelar-adds-support-for-polygon-amoy-and-linea-sepolia">support for Polygon Amoy and Linea Sepolia</a> on testnet.</p>
</li>
<li><p>Reached significant cross-chain transaction milestones.</p>
</li>
</ul>
<h3 id="heading-technical-achievements">Technical Achievements</h3>
<ul>
<li><p>Released <a target="_blank" href="https://blog.axelar.dev/">new tutorials for cross-chain development</a>.</p>
</li>
<li><p>Enhanced <a target="_blank" href="https://docs.axelar.dev/resources/ibc-chain-onboarding/">IBC chain connectivity</a>.</p>
</li>
<li><p>Improved documentation for interchain messaging.</p>
</li>
<li><p>Launched <a target="_blank" href="https://www.youtube.com/watch?v=M6JfvY4-APE">Farcaster Frame integration with Axelar GMP</a>.</p>
</li>
</ul>
<h3 id="heading-community-growth">Community Growth</h3>
<ul>
<li><p>Hosted multiple <a target="_blank" href="https://www.youtube.com/@axelar-network/streams">developer workshops</a>.</p>
</li>
<li><p>Expanded tutorial series for <a target="_blank" href="https://www.youtube.com/live/omaO6u4p8xA?si=64TtY19WZZLgoppQ">advanced token management</a>.</p>
</li>
<li><p>Enhanced <a target="_blank" href="https://www.youtube.com/live/v11GCdJ5ELE?si=CNzHB_AzPpxqFE-U">support for multichain RWA</a> development.</p>
</li>
</ul>
<h2 id="heading-q3-july-september">Q3 (July – September)</h2>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXf0kOO9KEZ99m0oMztyXjuL3mRb_a_WFBYnXiNViVBLTWsjVyLcnAf-mZwLeVCtlTz26SfQfFlHbusxIiYH3kLTfGEjpicH1zPmg7bkAshVKixLxxEBMJMn6ouMwBJfwAjNJ1BBsrXGFTF1UvbNvUuhKZDq?key=9XNuplkEyARSy7cpOYhHmQ" alt /></p>
<p>Q3 saw the development of core technologies and the expansion of cross-chain capabilities. Starting in July with the Interchain <a target="_blank" href="https://x.com/axelar/status/1823710944066986313">Amplifier’s testnet debut</a>, developers could deploy multichain stablecoins and enhance token functionality with ITS.</p>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXfZTFuf178zw3arGSBbF90BpI1HGNNKqypj3ZspfbIEGZVHn1Sa1-4o8oq7DxL0VBNQ3__g35GLRCuVUL6QBxX9i0AzDm48OBNSpunCFgslttQH2T91ohnOo-cixiymYxqGz1oeo1Gzl2eWmyWkhalWxABw?key=P0rO7SeD64db5hTEaGGFXg" alt /></p>
<p>In August, the Axelar network underwent its <a target="_blank" href="https://docs.axelar.dev/resources/contract-addresses/mainnet/#upgrade-path">mainnet upgrade</a> and <a target="_blank" href="https://www.axelar.network/blog/openzeppelin-and-axelar-collaborate-to-advance-ethereum-l2-interoperability">announced</a> a collaboration with <a target="_blank" href="https://www.openzeppelin.com/">OpenZeppelin</a> to standardize key interoperability standards. By September, the Amplifier's infrastructure was live on the mainnet, and the <a target="_blank" href="https://github.com/axelarnetwork/foundry-axelar-gmp-example">Foundry Axelar GMP example</a> repository included ITS examples. This positioned Axelar to offer unmatched flexibility and simplified cross-chain deployments as new integrations were introduced.</p>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXfTOt1VutCjryWyO2kL_2csFrYVf9CPDwi9jlcFfN1hYZfwUrC0KoPGnJmYgVpPUhwCKZ6n6aASR1vbEVtJucveStYtb1wCdVDZgT2eG269miyZvVKEJBgbn6Yery22HMpsxg9FwPCgipQaGD0g8tLXVR7x?key=iJIW6hzxF9rCKOtohDTIQA" alt /></p>
<h3 id="heading-major-developments-2">Major Developments</h3>
<ul>
<li><p>Successfully upgraded mainnet to <a target="_blank" href="https://docs.axelar.dev/resources/mainnet/upgrades/v1.0/">v1.0.2</a> (August 28).</p>
</li>
<li><p>Launched <a target="_blank" href="https://x.com/axelar/status/1825887799796752636">OpenZeppelin integration</a>.</p>
</li>
<li><p>Advanced <a target="_blank" href="https://docs.axelar.dev/resources/mainnet/upgrades/v1.0/">Interchain Amplifier</a> to testnet.</p>
</li>
<li><p>Released <a target="_blank" href="https://www.youtube.com/live/v11GCdJ5ELE?si=0Awcf9NK3NAOjln-">Multichain RWA lending</a> tutorials.</p>
</li>
</ul>
<h3 id="heading-technical-progress">Technical Progress</h3>
<ul>
<li><p>The <a target="_blank" href="https://github.com/axelarnetwork/foundry-axelar-gmp-example">Foundry Axelar GMP example</a> repository integrated Interchain Token Service.</p>
</li>
<li><p>Implemented mainnet deployment for <a target="_blank" href="https://docs.axelar.dev/dev/amplifier/introduction">Amplifier</a>.</p>
</li>
<li><p>Enhanced network stability and performance.</p>
</li>
<li><p>Introduced <code>BatchRequest</code> message type for granular transaction handling on the Network.</p>
</li>
<li><p>Improved chain connectivity with new IBC-related queries.</p>
</li>
</ul>
<h3 id="heading-developer-resources">Developer Resources</h3>
<ul>
<li><p>Released new documentation for <a target="_blank" href="https://docs.axelar.dev/validator/amplifier/verifier-onboarding/">Amplifier verifier onboarding</a>.</p>
</li>
<li><p>Produced advanced <a target="_blank" href="https://www.youtube.com/live/omaO6u4p8xA?si=tPFn6OI0INItEQAA">ITS token integration</a> tutorials.</p>
</li>
<li><p>Expanded <a target="_blank" href="https://docs.axelar.dev/dev/intro/#:~:text=Developer-,Guides,-Programmatically%20Create%20a">cross-chain development guides</a>.</p>
</li>
<li><p>Improved troubleshooting documentation based on developer queries and partner support.</p>
</li>
</ul>
<h2 id="heading-q4-october-december">Q4 (October – December)</h2>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXcTQH5Zl5eXCQQLn-cjXv3FuV346DV4JJDstYF1XyCAPHXeBN8iKJlxROapoaF3ua9x-5UiNayy-D7tso_bWAQDAiR-utT7HjvreB0_O5lfF4WYv8t8O73FUVqX2iTICHMezhve2Lhty3UwAy3kSpBjPM0o?key=l4vD9U9eNxOTLzXAGx_2pA" alt /></p>
<p>In the final quarter of 2024, Axelar demonstrated its growth as a top interoperability platform. During Q4, Axelar broadened its reach with the October launch of the <a target="_blank" href="https://docs.axelar.dev/dev/what-is-mobius-development-stack/">Mobius Development Stack (MDS)</a>. This allowed developers to combine on-chain and off-chain logic across various ecosystems, including the newly integrated <a target="_blank" href="https://flow.com/">Flow blockchain</a>, under the Interchain Amplifier.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734998781228/400c2058-63e2-4533-bbc7-33a6acc0d1af.png" alt class="image--center mx-auto" /></p>
<p>In November, events like Amplify Bangkok and ETHGlobal Bangkok highlighted Axelar’s community-driven innovation, with developers creating projects such as omnichain tokens and sovereign deployment tools.</p>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXdQFKXsTEdUIdZ0YJ6kppcySctABoBAXjqDcOXiVBkRwNh4-NZlvz4BwXQK1vSFJgpaDcTCcWlVggHIucxdb-JI_qPhjGK6s1SZphUSUMFY3fwNrshzvdSLMjOa6j1LOBKbFu9A?key=ZV48W-s6K8kdlBlE4d0NehIg" alt /></p>
<h3 id="heading-major-developments-3">Major Developments</h3>
<ul>
<li><p>Launched Axelar's <a target="_blank" href="https://docs.axelar.dev/dev/what-is-mobius-development-stack/">Mobius Development Stack (MDS).</a></p>
</li>
<li><p>Integrated Flow blockchain with Interchain Amplifier.</p>
</li>
<li><p>Surpassed <a target="_blank" href="https://axelarscan.io/">2 million cross-chain transactions</a>.</p>
</li>
<li><p>Connected to over <a target="_blank" href="https://axelarscan.io/#:~:text=Connected%20Chains%3A%2069">69 blockchain</a> networks.</p>
</li>
</ul>
<h3 id="heading-events">Events</h3>
<ul>
<li><p>Hosted <a target="_blank" href="https://www.youtube.com/watch?v=xPRLQFnJun4">Amplify Bangkok</a> alongside <a target="_blank" href="https://devcon.org/">Devcon</a>.</p>
</li>
<li><p>Sponsored <a target="_blank" href="https://ethglobal.com/events/bangkok">ETHGlobal Bangkok</a> Hackathon.</p>
</li>
<li><p>Showcased innovative projects, including Mooodeng, ETHVercel, and Swift Easy</p>
<ul>
<li><p><a target="_blank" href="https://ethglobal.com/showcase/mooodeng-xknzz">Mooodeng</a>: Mooodeng is an omnichain token solution integrating multiple cross-chain protocols, enabling seamless token transfers and interactions across blockchain ecosystems.</p>
</li>
<li><p><a target="_blank" href="https://ethglobal.com/showcase/ethvercel-inezg">ETHVercel:</a> ETHVercel enables the deployment of sovereign ap<a target="_blank" href="https://ethglobal.com/showcase/ethvercel-inezg">pli</a>cations with ZK-powered location validation. It earns Proof of Deployment tokens (ERC-5192) while maintaining granular access control in a collaborative ecosystem.</p>
</li>
<li><p><a target="_blank" href="https://ethglobal.com/showcase/swift-easy-v794z">Swift Eas</a><a target="_blank" href="https://ethglobal.com/showcase/ethvercel-inezg">y: Swift</a> Easy is a dual-ledger-based SWIFT extension for enterprise-grade cross-border payments.</p>
</li>
<li><p><a target="_blank" href="https://ethglobal.com/showcase/smooth-store-r7eni">Smooth Store</a>: SmoothStore is a decentralized storage platform with seamless onboarding using EIP-7702 biometric auth<a target="_blank" href="https://ethglobal.com/showcase/swift-easy-v794z">ent</a>ication, enabling secure file storage via FaceID or fingerprint.</p>
</li>
<li><p><a target="_blank" href="https://ethglobal.com/showcase/bs-itc-6ervw">BS-ITC</a>: BS-ITC enables cross-chain token tra<a target="_blank" href="https://ethglobal.com/showcase/bs-itc-6ervw">n</a>sfers, facilitating a smoother user experience for decentralized ecosystems.</p>
</li>
</ul>
</li>
<li><p>Conducted more developer workshops</p>
</li>
</ul>
<h3 id="heading-technical-achievements-1">Technical Achievements</h3>
<ul>
<li><p>Enhanced <a target="_blank" href="https://docs.axelar.dev/dev/send-tokens/introduction/">Interchain Token Service</a> Capabilities.</p>
</li>
<li><p>Expanded support for multiple blockchain ecosystems like the <a target="_blank" href="https://flow.com/">Flow blockchain</a> and <a target="_blank" href="https://hedera.com/">Hedera</a></p>
</li>
</ul>
<h2 id="heading-looking-forward-to-2025">Looking Forward to 2025</h2>
<p>As a transformative 2024 concludes, Axelar stands more potent than ever in its mission to build the Internet of Blockchains. The foundation laid this year through the Mobius Development Stack, Interchain Amplifier, and strategic partnerships positions Axelar for continued growth and innovation in 2025.</p>
<p>Key areas of focus for the coming year include:</p>
<ul>
<li><p>Further expansion of blockchain network integrations. Integrating prominent non-evm chains such as Sui, Stellar, Solana, and XRP.</p>
</li>
<li><p>Enhanced developer tools and resources.</p>
</li>
<li><p>Continued advancement of cross-chain technologies.</p>
</li>
<li><p>Deeper integration with emerging blockchain ecosystems</p>
</li>
</ul>
<p>The achievements of 2024 demonstrate technological advancement and a commitment to building a more accessible and interoperable Web3 ecosystem. As 2025 begins, Axelar continues to lead in blockchain interoperability, enabling developers to create the next generation of cross-chain applications.</p>
<p>For more information about Axelar and to stay updated on future developments, visit <a target="_blank" href="https://axelar.network">Axelar Network</a> or join our growing community on <a target="_blank" href="https://discord.com/invite/aRZ3Ra6f7D">Discord</a> and <a target="_blank" href="https://x.com/axelarnetwork">X (Twitter)</a>.</p>
]]></content:encoded></item><item><title><![CDATA[Axelar's Mobius Stack, Amplify Bangkok, ETHGlobal, & Dev Blog Highlights – November Dev Update 🕵️]]></title><description><![CDATA[Welcome to the November 2024 Axelar Developer Newsletter!
About Axelar: Axelar is the Web3 interoperability platform, delivering the shortest path to scale: an open stack to connect all blockchains. Adopters include Uniswap, Microsoft, and dozens of ...]]></description><link>https://blog.axelar.dev/axelars-mobius-stack-amplify-bangkok-ethglobal-dev-blog-highlights-november-dev-update</link><guid isPermaLink="true">https://blog.axelar.dev/axelars-mobius-stack-amplify-bangkok-ethglobal-dev-blog-highlights-november-dev-update</guid><category><![CDATA[axelar]]></category><category><![CDATA[newsletter]]></category><category><![CDATA[Ethereum]]></category><category><![CDATA[Blockchain]]></category><category><![CDATA[Developer]]></category><dc:creator><![CDATA[Idris Olubisi]]></dc:creator><pubDate>Fri, 29 Nov 2024 01:00:51 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1732811933641/579fed64-568e-46e6-b099-ad0d783dc545.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Welcome to the November 2024 Axelar Developer Newsletter!</p>
<p><strong>About Axelar:</strong> Axelar is the Web3 interoperability platform, delivering the shortest path to scale: an open stack to connect all blockchains. Adopters include Uniswap, Microsoft, and dozens of natively multichain startups, building applications to reach all blockchain users at once – <a target="_blank" href="https://twitter.com/bigjaymes_/status/1775223859173552139?s=20">10X as many active users</a> as the leading Web3 application environment.</p>
<p>This month, we're excited to share major progress and milestones in enhancing cross-chain interoperability with Axelar's Mobius Development Stack (MDS), unlocking a new omnichain design space for developers. We also highlight the Amplify Bangkok event, the ETHGlobal Bangkok Hackathon, and updates to our developer tools and documentation. </p>
<h2 id="heading-axelar-networks-2024-milestones-progress-update"><strong>🆙</strong> Axelar Network's 2024 Milestones - Progress Update</h2>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXcC5w98pTooj55j97Y_CbNx8uyQoLxTgwCAiYNd8Mu4LwG8sbsR26bkgn1x-8zB3BLGQ6thV1enDacALQ5RVl1bSZufQcC9V4VBBz_jlytR-PHyxwJazJyZcL_SHFXkTDR7EvatEQ?key=ZV48W-s6K8kdlBlE4d0NehIg" alt /></p>
<p><a target="_blank" href="https://docs.axelar.dev/dev/what-is-mobius-development-stack/">Axelar's Mobius Development Stack (MDS)</a> has officially launched, and it's just the beginning of a new era in cross-chain interoperability. With MDS, developers can seamlessly connect to over 60 blockchain ecosystems—including Solana, Sui, and XRP Ledger—while maintaining secure and open properties end-to-end.</p>
<p>Deploying a token that natively exists across multiple chains, preserving unique features like governance rights or yield mechanisms everywhere it's used, or effortlessly integrating augmented security by bonding restaked ETH and BTC through partnerships with <a target="_blank" href="https://www.eigenlayer.xyz/">EigenLayer</a> and <a target="_blank" href="https://babylonlabs.io/">Babylon</a>. With Axelar MDS, these possibilities are now a reality, opening up a world of new opportunities for decentralized applications.</p>
<p>Key components like the Interchain Token Service (ITS) and Axelar Virtual Machine (AVM) are now live on mainnet, enabling no-code token creation and programmable interchain logic. Plus, our collaboration with OpenZeppelin is set to establish standardized, vendor-agnostic cross-chain communication interfaces, empowering developers to build multichain dApps from day one. <a target="_blank" href="https://www.youtube.com/live/7MSQfVOXt1k?si=tJZOuXAmlZwli0Fw">Learn more</a>.</p>
<h2 id="heading-amplify-bangkok-devcon-2024">🎉 Amplify Bangkok @ Devcon 2024</h2>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXeWW50nw7cSfRzrL2GKfEXXcexkEaMfiHuwsPvBJt8IHfAwbwblYWP5dO01zv84qu1xNTatrs37V-jptwHGSaBfivuIBg_Q15mqs5HG1_zdvJIy5Ush_3VwEIEsdg-vrAX6a6Q0?key=ZV48W-s6K8kdlBlE4d0NehIg" alt /></p>
<p><strong>Amplify Bangkok</strong> brought together blockchain leaders, experts, and builders to explore cutting-edge advancements in interoperability, decentralized technologies, and cross-chain innovation. Hosted alongside Devcon, this event featured live debates, insightful talks from top industry speakers, and exciting networking opportunities. Keynote speakers included <strong>Andy</strong> from The Rollup, <strong>Camila Russo</strong> from The Defiant, <strong>Ed Felten</strong> from Arbitrum, and <strong>Georgios Vlachos</strong> from Axelar Protocol.</p>
<p>Missed it? Don’t worry —watch the video <a target="_blank" href="https://www.youtube.com/watch?v=xPRLQFnJun4">here</a>.</p>
<h2 id="heading-ethglobal-bangkok-hackathon">🔬 ETHGlobal Bangkok Hackathon</h2>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXfPcRd-7uFKurPuE9951bDRukyxS-X7WxhqDa6If8rrhUaRTcJ89_Aw7KUYzfgIIz-GPUW4JNr7BxGXrT3LeUnePHj4qTYYj9c-Rf-iQLfPL9rdyubok-7kZu8L_M5Km2-AZPYHcQ?key=ZV48W-s6K8kdlBlE4d0NehIg" alt /></p>
<p>We are excited to be a part of the ETHGlobal Bangkok Hackathon (November 15–17, 2024) by offering a bounty to developers from around the world who gathered in Thailand to explore solutions in interoperability, privacy, and decentralized systems. This event featured over 1,000 attendees, 68 protocols, and 61 workshops, with $750,000 in prizes across various categories, including Axelar's $4,000 bounty. </p>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXcyJrUd2dlqeGQPgMajafTINz4S26IULuiidgIdcWGsnxCHwb8beJmKXnl9hRw8f1mPTgIMjk2jxcH52Q1Bl1aAT0WvwBXyfXCD0JUEeMvatnID10Iv_Ag7hugiXzsxSAtKVC3mNA?key=ZV48W-s6K8kdlBlE4d0NehIg" alt /></p>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXfmteuSEP0f1itD7Tt7MRYTLxWrbctHZFe3X1wUd-G1LgCj35b3W4apiAWPHYN8OuSGAZ0NuDwYckIHeAR1U94IvE8frhVvRqEw1XBsYxu0GY7LMSuhvI6k0GJEqcGRAQ2Zge0i?key=ZV48W-s6K8kdlBlE4d0NehIg" alt /></p>
<p>Here are some of the standout projects from the event:</p>
<ul>
<li><p><a target="_blank" href="https://ethglobal.com/showcase/mooodeng-xknzz">Mooodeng</a>: Mooodeng is an omnichain token solution integrating multiple cross-chain protocols, enabling seamless token transfers and interactions across blockchain ecosystems.</p>
</li>
<li><p><a target="_blank" href="https://ethglobal.com/showcase/ethvercel-inezg">ETHVercel</a>: ETHVercel enables the deployment of sovereign applications with ZK-powered location validation, earning Proof of Deployment tokens (ERC-5192) while maintaining granular access control in a collaborative ecosystem.</p>
</li>
<li><p><a target="_blank" href="https://ethglobal.com/showcase/swift-easy-v794z">Swift Easy</a>: Swift Easy is a dual-ledger-based SWIFT extension designed for enterprise-grade cross-border payments.</p>
</li>
<li><p><a target="_blank" href="https://ethglobal.com/showcase/smooth-store-r7eni">Smooth Store</a>: SmoothStore is a decentralized storage platform with seamless onboarding using EIP-7702 biometric authentication, enabling secure file storage via FaceID or fingerprint.</p>
</li>
<li><p><a target="_blank" href="https://ethglobal.com/showcase/bs-itc-6ervw">BS-ITC</a>: BS-ITC enables cross-chain token transfers, facilitating a smoother user experience for decentralized ecosystems.</p>
</li>
</ul>
<p>This hackathon was a fantastic opportunity for developers to experiment, collaborate, and showcase their ideas. We look forward to seeing more innovative projects in future hackathons—stay tuned for even more events in 2025!</p>
<p>For more about Axelar and how we are helping to build the "Internet of Blockchains," check out <a target="_blank" href="http://axelar.network/">Axelar Network</a>“</p>
<h2 id="heading-new-tutorials-docs-and-more">📚 New Tutorials, Docs, and More</h2>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXdnyu_AspzvBZxcZ8z1t443yWyad0mAFK-SWfDGl5_qFteJ_foOZz2-I-fz3sRaYK18cIsolehV5Bs-CrWK_XnvXSY5cgGM_9hJTI3LqKsBOmUyw7YCJn_34EkCwQrL158NFHdlkQ?key=ZV48W-s6K8kdlBlE4d0NehIg" alt /></p>
<p>We've just published several technical articles and documentation updates.</p>
<h3 id="heading-axelar-gmp-amplifier">Axelar GMP / Amplifier</h3>
<ul>
<li><p><a target="_blank" href="https://blog.axelar.dev/amplifier-ampd-1-2-now-available">Amplifier ampd 1.2</a>: A daemon that is run by verifiers who form the decentralized group that vote on the truthfulness of cross-chain transactions.</p>
</li>
<li><p><a target="_blank" href="https://blog.axelar.dev/multichain-rwa-lending-with-axelar-gmp">Multichain RWA Lending with Axelar GMP</a>: how to build a multichain real-world asset lending platform using Axelar GMP.</p>
</li>
<li><p><a target="_blank" href="https://docs.axelar.dev/dev/cosmos-gmp/cosmos-2way-manual-relay/">Manual Relaying Cosmos 2-way Calls</a>: Learn how to manually relay Cosmos GMP 2-way calls</p>
</li>
</ul>
<h2 id="heading-catch-up-on-any-events-you-missed">🎤 Catch up on any events you missed</h2>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXclj9m8wNsm1xbKe475G5VXJ8Nl-s2HXpq5BXhDtTf6ZqTtLkJpKe6fNRM8gNN2bpQtGvAs9uPqUM6f5O-N8JUrBPdlJ7lgkOgBIY4RICWSRKTPTVn5murVjrWHUnSEoYELoO3QVw?key=ZV48W-s6K8kdlBlE4d0NehIg" alt /></p>
<p>Did you miss our recent talks? Here are some highlights:</p>
<ul>
<li><p><a target="_blank" href="https://www.youtube.com/watch?v=_e4DgyBQanQ">Multichain Gas Estimation &amp; Optimisation with Axelar</a></p>
</li>
<li><p><a target="_blank" href="https://www.youtube.com/watch?v=7MSQfVOXt1k">Axelar's Mobius Development Stack: Milestones + Progress</a></p>
</li>
<li><p><a target="_blank" href="https://www.youtube.com/watch?v=j6KF0qWJw08">Tracking and Troubleshooting with Axelarjs SDK and Axelarscan</a> </p>
</li>
</ul>
<h2 id="heading-stay-connected"><strong>📌 Stay Connected</strong></h2>
<p>We have a lot more planned for the upcoming months, so you won’t want to miss out.</p>
<ul>
<li><p><strong>🐦 Follow us on</strong> <a target="_blank" href="https://x.com/axelarnetwork"><strong>X (Twitter)</strong></a> to stay updated on upcoming developer content and live events.</p>
</li>
<li><p><strong>💬 Join our</strong> <a target="_blank" href="https://discord.com/invite/aRZ3Ra6f7D"><strong>Discord community</strong></a> for real-time discussions and support.</p>
</li>
<li><p><strong>📰 Subscribe to the</strong> <a target="_blank" href="https://blog.axelar.dev/newsletter"><strong>Axelar Developer blog</strong></a> to stay up to date on the latest Axelar news.</p>
</li>
</ul>
<hr />
<p>Thank you for being a part of the Axelar community. We can't wait to see what you'll build next!</p>
]]></content:encoded></item><item><title><![CDATA[Axelar's Mobius Development Stack, Flow Integration, Multichain RWA, Dev Blog and Docs – October Dev Update 🕵️]]></title><description><![CDATA[Welcome to the October 2024 Axelar Developer Newsletter!
About Axelar: Axelar is the Web3 interoperability platform, delivering the shortest path to scale: an open stack to connect all blockchains. Adopters include Uniswap, Microsoft, and dozens of n...]]></description><link>https://blog.axelar.dev/axelars-mobius-development-stack-flow-integration-multichain-rwa-dev-blog-and-docs-october-dev-update</link><guid isPermaLink="true">https://blog.axelar.dev/axelars-mobius-development-stack-flow-integration-multichain-rwa-dev-blog-and-docs-october-dev-update</guid><category><![CDATA[axelar]]></category><category><![CDATA[Blockchain]]></category><category><![CDATA[Web3]]></category><category><![CDATA[flow]]></category><category><![CDATA[software development]]></category><category><![CDATA[Smart Contracts]]></category><category><![CDATA[newsletter]]></category><dc:creator><![CDATA[Idris Olubisi]]></dc:creator><pubDate>Thu, 31 Oct 2024 15:55:31 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1730390008796/e35017da-111e-4313-b7ec-2f6ff7c695b5.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Welcome to the October 2024 Axelar Developer Newsletter!</p>
<p><strong>About Axelar:</strong> Axelar is the Web3 interoperability platform, delivering the shortest path to scale: an open stack to connect all blockchains. Adopters include Uniswap, Microsoft, and dozens of natively multichain startups, building applications to reach all blockchain users at once – <a target="_blank" href="https://twitter.com/bigjaymes_/status/1775223859173552139?s=20">10X as many active users</a> as the leading Web3 application environment.</p>
<p>This month, we're excited to share major milestones in enhancing cross-chain interoperability. We've launched Axelar's Mobius Development Stack (MDS), unlocking a new omnichain design space for developers. Additionally, the <a target="_blank" href="https://flow.com/">Flow blockchain</a> is now integrated with our Interchain Amplifier, expanding seamless connectivity across networks. We've also released updates to our developer tools and documentation.</p>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXdJo8fTRdx82IDybWh80PpM128kB-r0FaN5T0ax7gLvsAGNZa3CcBqCu_38NwnUZTP6zlfPSE9JoY1vFhEKOrh07ptFd8WNZXSqGE3fzx7x7uNGanly_IEuamHQ0J8qyNkiGabeUPALyB4jObfoY5XWvuoD?key=l4vD9U9eNxOTLzXAGx_2pA" alt /></p>
<h2 id="heading-axelars-mobius-development-stack"><strong>🆙</strong> Axelar's Mobius Development Stack</h2>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXf7RkOttrFOdkCB5gkKtLwg77UZByYXQYo_tb9-_N0zt0kTXKec2uarlRBMzyaBnJAbKLvXAAEcGhQoEA0IE-k7kzwq-r840evBaQwKEYsn6ue8TiYupqY1RlwkPNnrTgBFrxOJ_gm8J2bLuzERKwyevma4?key=l4vD9U9eNxOTLzXAGx_2pA" alt /></p>
<p>Axelar has introduced MDS, a suite of open tools and protocols that open up an entirely new omnichain design space. Now, applications can seamlessly connect to users and logic anywhere on the internet while maintaining verified and open properties end-to-end.</p>
<p>Imagine this: a user sends a message on Telegram that rebalances a vault on <strong>Sui</strong>, which then interacts with DeFi protocols on <strong>Arbitrum</strong> and even a private blockchain of a financial institution. With Axelar MDS, such integration isn't just possible—it's effortless. This level of interoperability opens up a world of new possibilities for decentralized applications.</p>
<p>If you're looking to build the next generation of omnichain dApps, Axelar MDS might just be the toolkit you need! <a target="_blank" href="https://docs.axelar.dev/dev/what-is-mobius-development-stack/">Learn more</a>.</p>
<h2 id="heading-flow-blockchain-integration-with-interchain-amplifier">🔬 Flow Blockchain Integration with Interchain Amplifier</h2>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXdCmAHKhnERmBrs8NbYxJSvPmjeHKZTENanylOmIUXUsQy1ih5g7LLN9b3LMxFoKheAQS3etz9mVnyEXWAW2vH7r_9Vi9rt-dKBJgwlYurReWZpxYzZ5EKuH0QHRemAORef-bXcYq9xSyagoDtv9y58F-ce?key=l4vD9U9eNxOTLzXAGx_2pA" alt /></p>
<p>We're excited to announce that Axelar has integrated the <a target="_blank" href="https://flow.com/">Flow blockchain</a> with the Interchain Amplifier, expanding the horizons for developers building on Flow. </p>
<p>This integration enables seamless cross-chain communication and asset transfers via Amplifier between Flow and other connected networks. Now, you can leverage Axelar's secure cross-chain messaging protocols to enhance your Flow-based applications, making them interoperable with a broader ecosystem.</p>
<p>Curious? Get started <a target="_blank" href="https://docs.axelar.dev/dev/amplifier/introduction">here</a>.</p>
<h2 id="heading-new-tutorials-docs-and-more">📚 New Tutorials, Docs, and More</h2>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXdBuK-xzr-OQIW1W42RS_xg_bGdNpQ-iAnA6BXnZB1tgfMEmVqRAlY-EofEmdoPpUwrn38eATcCkejC_N_bryyxq0yb1AjoGE9t1H36QlfC6sIu1_pMSmaF5UjwefsKzcLWGhE0z0WG9zqphkkFEkAvxpPL?key=l4vD9U9eNxOTLzXAGx_2pA" alt /></p>
<p>We've just published several technical articles and documentation updates.</p>
<h3 id="heading-axelar-gmp">Axelar GMP</h3>
<ul>
<li><p><a target="_blank" href="https://blog.axelar.dev/multichain-rwa-lending-with-axelar-gmp">Multichain RWA Lending</a> <a target="_blank" href="https://docs.axelar.dev/dev/amplifier/introduction">wit</a><a target="_blank" href="https://blog.axelar.dev/multichain-rwa-lending-with-axelar-gmp">h Axelar GMP</a>: how to build a multichain real-world asset lending platform using Axelar GMP.</p>
</li>
<li><p><a target="_blank" href="https://docs.axelar.dev/dev/cosmos-gmp/cosmos-2way-manual-relay/">Manual Relaying Cosmos 2-way Calls</a>: Learn how to manually relay Cosmos GMP 2-way calls</p>
</li>
</ul>
<h3 id="heading-its">ITS</h3>
<ul>
<li><p><a target="_blank" href="https://blog.axelar.dev/cross-chain-memecoins-with-axelar">Cross-Chain Memecoins With Axelar</a>: Learn how to deploy and use your cross-chain memecoin both via the no-<a target="_blank" href="https://docs.axelar.dev/dev/amplifier/introduction">code</a> portal and the programmatic solutions.</p>
</li>
<li><p><a target="_blank" href="https://docs.axelar.dev/dev/send-tokens/interchain-tokens/token-manager/">Token Manager Types</a>: Learn how Token Manager contracts facilitate the connection between your interchain token and the Interchain Token Service (ITS).</p>
</li>
</ul>
<h2 id="heading-catch-up-on-any-events-you-missed">🎤 Catch up on any events you missed</h2>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXe2ihbhao1mOqLyPYrOwGEklLpEWksd8kUHHlVG4FZ6ULI8fVn3EmEIA80kDRxZpBX0ZEV4j3vmw9nvPOVKjZnRpbKfUmW-WM1v_e2nBCIUNL56su6_tF9Rr2cuFM2aKnoYnt6M4XFajg561S-z9x0ybl6h?key=l4vD9U9eNxOTLzXAGx_2pA" alt /></p>
<p>Did you miss our recent talks? Here are some highlights:</p>
<ul>
<li><p><a target="_blank" href="https://www.youtube.com/watch?v=j6KF0qWJw08">Tracking and Troubleshooting with Axelarjs SDK and Axelarscan</a> </p>
</li>
<li><p><a target="_blank" href="https://www.youtube.com/live/7MSQfVOXt1k?si=dgH0kobVhSJ1RVfi">Axelar's Mobius Development Stack: Milestones + Progress</a></p>
</li>
<li><p><a target="_blank" href="https://www.youtube.com/live/_IgpqXDf4Lg?si=Q_QOcDcDz82Lz_PG">A Hitchhiker’s Guide to Multichain dApps</a></p>
</li>
</ul>
<h2 id="heading-stay-connected"><strong>📌 Stay Connected</strong></h2>
<p>We have a lot more planned for the upcoming months, so you won’t want to miss out.</p>
<ul>
<li><p><strong>🐦 Follow us on</strong> <a target="_blank" href="https://x.com/axelarnetwork"><strong>X (Twitter)</strong></a> to stay updated on upcoming developer content and live events.</p>
</li>
<li><p><strong>💬 Join our</strong> <a target="_blank" href="https://discord.com/invite/aRZ3Ra6f7D"><strong>Discord community</strong></a> for real-time discussions and support.</p>
</li>
<li><p><strong>📰 Subscribe to the</strong> <a target="_blank" href="https://blog.axelar.dev/newsletter"><strong>Axelar Developer blog</strong></a> to stay up to date on the latest Axelar news.</p>
</li>
</ul>
<p>Thank you for being a part of the Axelar community. We can't wait to see what you'll build next!</p>
]]></content:encoded></item><item><title><![CDATA[Amplifier ampd 1.2 Now Available]]></title><description><![CDATA[We’re pleased to announce the release of ampd version 1.2.
What is ampd?
ampd is part of the Interchain Amplifier. It is a daemon that is run by verifiers who form the decentralized group that vote on the truthfulness of cross-chain transactions. amp...]]></description><link>https://blog.axelar.dev/amplifier-ampd-1-2-now-available</link><guid isPermaLink="true">https://blog.axelar.dev/amplifier-ampd-1-2-now-available</guid><category><![CDATA[software development]]></category><category><![CDATA[Blockchain]]></category><dc:creator><![CDATA[Stephen Fluin]]></dc:creator><pubDate>Mon, 14 Oct 2024 07:31:22 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1728487237435/59bd7a33-112b-4845-8d52-c546b0ebcc06.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>We’re pleased to announce <a target="_blank" href="https://github.com/axelarnetwork/axelar-amplifier/releases/tag/ampd-v1.2.0">the release</a> of <code>ampd</code> version 1.2.</p>
<h2 id="heading-what-is-ampd">What is <code>ampd</code>?</h2>
<p><code>ampd</code> is part of the <a target="_blank" href="https://docs.axelar.dev/dev/amplifier/introduction/">Interchain Amplifier</a>. It is a daemon that is run by <a target="_blank" href="https://docs.axelar.dev/validator/amplifier/verifier-onboarding/">verifiers</a> who form the decentralized group that vote on the truthfulness of cross-chain transactions. <code>ampd</code> looks on-chain for polls and signing requests, and then checks independent sources for the truthfulness of transactions and votes on-chain.</p>
<h2 id="heading-whats-new">What’s new?</h2>
<p>Version 1.2 adds features and improves the debuggability of transactions:</p>
<ul>
<li><p>adds the ability to send tokens from a verifier using the underlying <code>tofnd</code> cryptographic library and keys</p>
<ul>
<li><p><strong>ampd send-tokens</strong> &lt;TO_ADDRESS&gt; &lt;AMOUNT&gt; &lt;DENOM&gt;</p>
</li>
<li><p>eg. <code>ampd send-tokens axelar16dxsfhyegy40e4eqfxee5jw5gyy2xxtcw4t2na 1000000 uaxl</code></p>
</li>
</ul>
</li>
<li><p>verifiers can set a proxy address to receive rewards for contributions. Instead of going directly to the verifier, rewards will be paid to the address supplied. This depends on a future release of Rewards 1.1 on amplifier.</p>
<ul>
<li><strong>ampd set-rewards-proxy</strong> &lt;PROXY_ADDRESS&gt;</li>
</ul>
</li>
<li><p>more information about failures are presented to users</p>
</li>
<li><p>the ability to configure the log level with <code>RUST_LOG</code> environmental variable</p>
</li>
</ul>
<h2 id="heading-whats-next">What’s next?</h2>
<p>The team is continuing to work on the plugin architecture and the addition of support for new chain tech stacks.</p>
]]></content:encoded></item><item><title><![CDATA[Multichain RWA Lending with Axelar GMP]]></title><description><![CDATA[Today, we see many different networks, each with its own strengths and limitations. This has created significant challenges, leading to scattered liquidity and complicated user experiences, especially in Real World Asset (RWA) lending.
To tackle thes...]]></description><link>https://blog.axelar.dev/multichain-rwa-lending-with-axelar-gmp</link><guid isPermaLink="true">https://blog.axelar.dev/multichain-rwa-lending-with-axelar-gmp</guid><category><![CDATA[axelar]]></category><category><![CDATA[Solidity]]></category><category><![CDATA[RWA Tokenization ]]></category><category><![CDATA[Smart Contracts]]></category><category><![CDATA[Web3]]></category><category><![CDATA[Remix]]></category><category><![CDATA[remix ide]]></category><dc:creator><![CDATA[Idris Olubisi]]></dc:creator><pubDate>Wed, 09 Oct 2024 12:46:03 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1728304258227/583f678e-cd2b-4b24-9116-f57876160d58.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Today, we see many different networks, each with its own strengths and limitations. This has created significant challenges, leading to scattered liquidity and complicated user experiences, especially in Real World Asset (RWA) lending.</p>
<p>To tackle these challenges, Axelar, the leading Web3 interoperability platform, has a feature called <a target="_blank" href="https://docs.axelar.dev/dev/general-message-passing/overview">Axelar's General Message Passing (GMP)</a>, which offers an effective and scalable solution. It enables secure and efficient communication between blockchains beyond simple asset transfers.</p>
<p>To understand how Axelar's GMP can impact real-world scenarios, let's consider an example of how blockchain technology is already changing lives.</p>
<p>A farmer named Amani lives in a small village with acres of fertile land but can't get a loan from local banks because he lacks a traditional credit score. Now, think of Sarah, a tech entrepreneur in New York working on blockchain solutions. Their worlds seem far apart, but blockchain technology could connect them. Consider <a target="_blank" href="https://goldfinch.finance/">Goldfinch</a>, a real-world example in the DeFi space. It allows borrowers from emerging markets to secure loans using real-world assets as collateral, funded by global investors who trust in blockchain's transparency. This system opens doors for people previously excluded from the financial system.</p>
<p>Now, imagine scaling this idea across multiple blockchains, each optimized for different strengths like speed, security, or low fees. A multichain platform could tap into the best of each world, creating a truly global lending ecosystem that operates 24/7, without borders, and with minimal friction.</p>
<p>In this guide, we'll explore how to build a multichain real-world asset lending platform using Axelar GMP. If you want to see the complete code, you can find it on GitHub <a target="_blank" href="https://gist.github.com/Olanetsoft/1689f5860413478d0f82aaf90051b31a"><strong>here</strong></a>.</p>
<h2 id="heading-what-is-a-real-world-asset-rwa">What is a Real-world Asset (RWA)?</h2>
<p>A <a target="_blank" href="https://www.coinbase.com/en-gb/learn/crypto-glossary/what-are-real-world-assets-rwa">Real-World Asset (RWA)</a> is a digital representation of a tangible or intangible asset that exists outside the blockchain ecosystem. These digital tokens symbolize ownership or rights to various types of assets, such as:</p>
<ol>
<li><p>Real estate.</p>
</li>
<li><p>Commodities (e.g., gold, oil).</p>
</li>
<li><p>Fine art.</p>
</li>
<li><p>Intellectual property.</p>
</li>
<li><p>Financial instruments (e.g., stocks, bonds).</p>
</li>
</ol>
<p>The process of creating these digital representations is called <strong>tokenization</strong>. This involves converting real-world assets into blockchain-based tokens. The following are the advantages of tokenization:</p>
<ol>
<li><p>Increased liquidity: Assets previously difficult to divide or trade can now be easily bought and sold in smaller fractions.</p>
</li>
<li><p>Broader accessibility: Investors can access a wider range of assets with lower capital requirements.</p>
</li>
<li><p>Improved transparency: Blockchain technology provides a clear, immutable record of ownership and transactions.</p>
</li>
<li><p>Enhanced efficiency: Tokenization can streamline various processes by reducing administrative overhead and costs.</p>
</li>
</ol>
<h2 id="heading-prerequisites">Prerequisites</h2>
<ul>
<li><p>A good understanding of <a target="_blank" href="https://www.tutorialspoint.com/solidity/index.htm"><strong>Solidity</strong></a><strong>.</strong></p>
</li>
<li><p>A <a target="_blank" href="https://metamask.io/">MetaMask wallet</a> with FTM and Celo funds for testing. If you don’t have these funds, you can get FTM from the <a target="_blank" href="https://faucet.fantom.network/">Fantom faucet</a> and Celo from the <a target="_blank" href="https://faucet.celo.org/alfajores">Celo faucets</a>.</p>
</li>
<li><p><code>aUSDC</code> <a target="_blank" href="https://discord.com/invite/aRZ3Ra6f7D">faucet</a>.</p>
</li>
<li><p>Familiarity with the <a target="_blank" href="http://remix.ethereum.org/">remix.ethereum.org</a> portal.</p>
</li>
</ul>
<p>Before we get started, let's outline what we'll be doing and why each component is important for our multichain RWA lending platform:</p>
<ol>
<li><p><code>MockRWAToken</code>: This contract will simulate a tokenized real-world asset. For our demonstration, we'll create a simplified version that allows us to mint and transfer tokens.</p>
</li>
<li><p><code>RWAOracle</code>: This contract will act as a price feed for our RWA tokens. For our purposes, we'll create a simple oracle that allows us to set and update asset values manually.</p>
</li>
<li><p><code>LendingPool</code>: This is the core contract of our platform. It will handle the creation of loans, manage collateral, and facilitate cross-chain interactions using Axelar GMP.</p>
</li>
</ol>
<p>By creating these contracts, we can simulate a simple RWA lending platform that works across different blockchains. This setup will let users, like our example farmer Amani, use their tokenized real-world assets as collateral, even if the lender is on another blockchain network.</p>
<p>Next, we'll start by creating the <code>MockRWAToken</code>. This will serve as the foundation for our platform, representing the tokenized real-world assets that can be used as collateral.</p>
<h2 id="heading-create-a-mock-rwa-token">Create a Mock RWA Token</h2>
<p>To begin your implementation, you’ll start by creating a <code>MockRWAToken</code> contract. This will serve as a representation of tokenized real-world assets.</p>
<ul>
<li><p>Navigate to <a target="_blank" href="http://remix.ethereum.org">remix.ethereum.org</a>.</p>
</li>
<li><p>Create a new folder named "contracts".</p>
</li>
<li><p>Inside this folder, create a new file called <code>MockRWAToken.sol</code>.</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728156591878/60b0df53-6543-4f1d-a9e2-3df4c2de0405.png" alt="Navigate to remix.ethereum.org" class="image--center mx-auto" /></p>
<p>Add the following code snippet to the file:</p>
<pre><code class="lang-solidity"><span class="hljs-comment">// SPDX-License-Identifier: MIT</span>
<span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> ^0.8.0;</span>

<span class="hljs-keyword">import</span> <span class="hljs-string">"@openzeppelin/contracts/token/ERC721/ERC721.sol"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"@openzeppelin/contracts/access/Ownable.sol"</span>;

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">MockRWAToken</span> <span class="hljs-keyword">is</span> <span class="hljs-title">ERC721</span>, <span class="hljs-title">Ownable</span> </span>{
    <span class="hljs-keyword">uint256</span> <span class="hljs-keyword">private</span> _nextTokenId;

    <span class="hljs-function"><span class="hljs-keyword">constructor</span>(<span class="hljs-params">
        <span class="hljs-keyword">address</span> initialOwner
    </span>) <span class="hljs-title">ERC721</span>(<span class="hljs-params"><span class="hljs-string">"Mock RWA"</span>, <span class="hljs-string">"MRWA"</span></span>) <span class="hljs-title">Ownable</span>(<span class="hljs-params">initialOwner</span>) </span>{}

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">safeMint</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> to</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title">onlyOwner</span> </span>{
        <span class="hljs-keyword">uint256</span> tokenId <span class="hljs-operator">=</span> _nextTokenId<span class="hljs-operator">+</span><span class="hljs-operator">+</span>;
        _safeMint(to, tokenId);
    }
}
</code></pre>
<p>In the code snippet above, you:</p>
<ul>
<li><p>Created an ERC721 token contract named "Mock RWA" with the symbol "MRWA"</p>
</li>
<li><p>Implemented a <code>safeMint</code> function that allows the contract owner to create new tokens</p>
</li>
<li><p>Used OpenZeppelin's ERC721 and Ownable contracts for standard functionality and access control</p>
</li>
</ul>
<p>In the next step, you will create the <code>RWAOracle</code> contract, which will provide price information for your tokenized assets. This oracle will help determine the value of the assets used as collateral in your lending platform.</p>
<h2 id="heading-create-a-mock-rwa-oracle">Create a Mock RWA Oracle</h2>
<p>In your <code>contracts</code> folder, create a new file named <code>RWAOracle.sol</code> add the following code snippet:</p>
<pre><code class="lang-solidity"><span class="hljs-comment">// SPDX-License-Identifier: MIT</span>
<span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> ^0.8.0;</span>

<span class="hljs-keyword">import</span> <span class="hljs-string">"@openzeppelin/contracts/access/Ownable.sol"</span>;

<span class="hljs-comment">// RWA Oracle</span>
<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">RWAOracle</span> <span class="hljs-keyword">is</span> <span class="hljs-title">Ownable</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">constructor</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> initialOwner</span>) <span class="hljs-title">Ownable</span>(<span class="hljs-params">initialOwner</span>) </span>{}

    <span class="hljs-keyword">mapping</span>(<span class="hljs-keyword">uint256</span> <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> <span class="hljs-keyword">uint256</span>) <span class="hljs-keyword">private</span> rwaValues;

    <span class="hljs-function"><span class="hljs-keyword">event</span> <span class="hljs-title">RWAValueUpdated</span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span> <span class="hljs-keyword">indexed</span> tokenId, <span class="hljs-keyword">uint256</span> value</span>)</span>;

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">updateRWAValue</span>(<span class="hljs-params">
        <span class="hljs-keyword">uint256</span> _tokenId,
        <span class="hljs-keyword">uint256</span> _value
    </span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title">onlyOwner</span> </span>{
        rwaValues[_tokenId] <span class="hljs-operator">=</span> _value;
        <span class="hljs-keyword">emit</span> RWAValueUpdated(_tokenId, _value);
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getRWAValue</span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span> _tokenId</span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title"><span class="hljs-keyword">view</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">uint256</span></span>) </span>{
        <span class="hljs-keyword">return</span> rwaValues[_tokenId];
    }
}
</code></pre>
<p>This contract provides two key functions:</p>
<ul>
<li><p><code>updateRWAValue</code>: Allows the contract owner to set or update the value of an RWA token.</p>
</li>
<li><p><code>getRWAValue</code>: Retrieves the current value of a specific RWA token</p>
</li>
</ul>
<blockquote>
<p>In a production environment, this oracle would connect with real-world data sources to provide accurate, up-to-date asset valuations. For our demonstration, this simplified version is enough to show the main features of our lending platform.</p>
</blockquote>
<p>Next, you'll create the <code>LendingPool</code> contract, which will connect the <code>MockRWAToken</code> and <code>RWAOracle</code> to enable cross-chain lending operations.</p>
<h2 id="heading-create-the-lending-pool-contract">Create the Lending Pool Contract</h2>
<p>Now that you have your <code>MockRWAToken</code> and <code>RWAOracle</code> ready, you can move on to creating the <code>LendingPool</code> contract. In your <code>contracts</code> folder, create a new file named <code>LendingPool.sol</code>.</p>
<h3 id="heading-import-necessary-contracts">Import Necessary Contracts</h3>
<p>Add the following code snippet to import the necessary contracts.</p>
<pre><code class="lang-solidity"><span class="hljs-comment">// SPDX-License-Identifier: MIT</span>
<span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> ^0.8.0;</span>

<span class="hljs-comment">// Import required OpenZeppelin contracts</span>
<span class="hljs-keyword">import</span> <span class="hljs-string">"@openzeppelin/contracts/token/ERC721/ERC721.sol"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"@openzeppelin/contracts/security/ReentrancyGuard.sol"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"@openzeppelin/contracts/access/Ownable.sol"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"</span>;

<span class="hljs-comment">// Import Axelar contracts for cross-chain functionality</span>
<span class="hljs-keyword">import</span> <span class="hljs-string">"@axelar-network/axelar-gmp-sdk-solidity/contracts/executable/AxelarExecutable.sol"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IAxelarGasService.sol"</span>;

<span class="hljs-comment">// Import our custom RWAOracle contract</span>
<span class="hljs-keyword">import</span> <span class="hljs-string">"./RWAOracle.sol"</span>;

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">LendingPool</span> <span class="hljs-keyword">is</span> <span class="hljs-title">AxelarExecutable</span>, <span class="hljs-title">ReentrancyGuard</span>, <span class="hljs-title">Ownable</span> </span>{

    <span class="hljs-comment">// Contract code here</span>

}
</code></pre>
<h3 id="heading-add-state-variables-structs-and-events">Add State Variables, Structs, and Events</h3>
<pre><code class="lang-solidity"><span class="hljs-comment">//...</span>

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">LendingPool</span> <span class="hljs-keyword">is</span> <span class="hljs-title">AxelarExecutable</span>, <span class="hljs-title">ReentrancyGuard</span>, <span class="hljs-title">Ownable</span> </span>{

        <span class="hljs-comment">// Main contract interfaces</span>
        IERC20Metadata <span class="hljs-keyword">public</span> lendingToken;
        ERC721 <span class="hljs-keyword">public</span> rwaToken;
        RWAOracle <span class="hljs-keyword">public</span> rwaOracle;
        IAxelarGasService <span class="hljs-keyword">public</span> <span class="hljs-keyword">immutable</span> gasService;

        <span class="hljs-comment">// Constants for loan parameters</span>
        <span class="hljs-keyword">uint256</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">constant</span> LIQUIDATION_THRESHOLD <span class="hljs-operator">=</span> <span class="hljs-number">150</span>;
        <span class="hljs-keyword">uint256</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">constant</span> INTEREST_RATE <span class="hljs-operator">=</span> <span class="hljs-number">5</span>;

        <span class="hljs-comment">// Cross-chain source information</span>
        <span class="hljs-keyword">string</span> <span class="hljs-keyword">public</span> sourceAddress;
        <span class="hljs-keyword">string</span> <span class="hljs-keyword">public</span> sourceChain;

        <span class="hljs-comment">// Loan struct to store loan information</span>
        <span class="hljs-keyword">struct</span> <span class="hljs-title">Loan</span> {
            <span class="hljs-keyword">uint256</span> amount;
            <span class="hljs-keyword">uint256</span> collateralId;
            <span class="hljs-keyword">uint256</span> startTime;
            <span class="hljs-keyword">uint256</span> duration;
            <span class="hljs-keyword">address</span> borrower;
            <span class="hljs-keyword">bool</span> isActive;
        }

        <span class="hljs-comment">// Mapping to store loans by ID</span>
        <span class="hljs-keyword">mapping</span>(<span class="hljs-keyword">uint256</span> <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> Loan) <span class="hljs-keyword">public</span> loans;
        <span class="hljs-keyword">uint256</span> <span class="hljs-keyword">public</span> nextLoanId;

        <span class="hljs-comment">// Events for various loan actions</span>
        <span class="hljs-function"><span class="hljs-keyword">event</span> <span class="hljs-title">LoanCreated</span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span> loanId, <span class="hljs-keyword">address</span> borrower, <span class="hljs-keyword">uint256</span> amount, <span class="hljs-keyword">uint256</span> collateralId</span>)</span>;
        <span class="hljs-function"><span class="hljs-keyword">event</span> <span class="hljs-title">LoanRepaid</span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span> loanId</span>)</span>;
        <span class="hljs-function"><span class="hljs-keyword">event</span> <span class="hljs-title">LoanLiquidated</span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span> loanId, <span class="hljs-keyword">address</span> liquidator</span>)</span>;
        <span class="hljs-function"><span class="hljs-keyword">event</span> <span class="hljs-title">CrossChainLoanRepaid</span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span> loanId</span>)</span>;
        <span class="hljs-function"><span class="hljs-keyword">event</span> <span class="hljs-title">CollateralReleased</span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span> loanId, <span class="hljs-keyword">uint256</span> collateralId, <span class="hljs-keyword">address</span> borrower</span>)</span>;
}
</code></pre>
<p>In the code above, you:</p>
<ul>
<li><p>Defined key contract components: tokens, oracle, loan parameters</p>
</li>
<li><p>Created Loan <code>struct</code> to store loan information</p>
</li>
<li><p>Created events for contract actions like <code>LoanCreated</code>, <code>LoanRepaid</code>, <code>LoanLiquidated</code>, <code>CrossChainLoanRepaid</code>, <code>CollateralReleased</code></p>
</li>
</ul>
<p>Ignore the red lines showing on your remix right now; you will fix it in a bit.</p>
<h3 id="heading-implement-the-constructor">Implement the Constructor</h3>
<pre><code class="lang-solidity"><span class="hljs-comment">//...</span>
<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">LendingPool</span> <span class="hljs-keyword">is</span> <span class="hljs-title">AxelarExecutable</span>, <span class="hljs-title">ReentrancyGuard</span>, <span class="hljs-title">Ownable</span> </span>{

    <span class="hljs-comment">//...</span>

    <span class="hljs-function"><span class="hljs-keyword">constructor</span>(<span class="hljs-params">
        <span class="hljs-keyword">address</span> _initialOwner,
        <span class="hljs-keyword">address</span> _gateway,
        <span class="hljs-keyword">address</span> _gasService,
        <span class="hljs-keyword">address</span> _lendingToken,
        <span class="hljs-keyword">address</span> _rwaToken,
        <span class="hljs-keyword">address</span> _rwaOracle
    </span>) <span class="hljs-title">AxelarExecutable</span>(<span class="hljs-params">_gateway</span>) <span class="hljs-title">Ownable</span>(<span class="hljs-params">_initialOwner</span>) </span>{
        <span class="hljs-comment">// Initialize contract components</span>
        gasService <span class="hljs-operator">=</span> IAxelarGasService(_gasService);
        lendingToken <span class="hljs-operator">=</span> IERC20Metadata(_lendingToken);
        rwaToken <span class="hljs-operator">=</span> ERC721(_rwaToken);
        rwaOracle <span class="hljs-operator">=</span> RWAOracle(_rwaOracle);
    }

}
</code></pre>
<p>In the code above, you implemented the constructor, set up the contract with the necessary addresses, and initialized the inherited contracts.</p>
<p>Next, you will proceed to implement the main functions, starting with a function to initiate a multichain loan.</p>
<h3 id="heading-create-a-multichain-loan-function">Create a Multichain Loan Function</h3>
<p>This function allows users to initiate a loan on a different blockchain using their RWA token as collateral. To do this, add the following code to your <code>LendingPool</code> contract:</p>
<pre><code class="lang-solidity"><span class="hljs-comment">//...</span>
<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">LendingPool</span> <span class="hljs-keyword">is</span> <span class="hljs-title">AxelarExecutable</span>, <span class="hljs-title">ReentrancyGuard</span>, <span class="hljs-title">Ownable</span> </span>{

    <span class="hljs-comment">//...</span>

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">initiateCrossChainLoan</span>(<span class="hljs-params">
        <span class="hljs-keyword">string</span> <span class="hljs-keyword">memory</span> destinationChain,
        <span class="hljs-keyword">string</span> <span class="hljs-keyword">memory</span> destinationAddress,
        <span class="hljs-keyword">uint256</span> _amount,
        <span class="hljs-keyword">uint256</span> _collateralId,
        <span class="hljs-keyword">uint256</span> _duration
    </span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title"><span class="hljs-keyword">payable</span></span> </span>{
        <span class="hljs-comment">// Ensure gas payment is provided</span>
        <span class="hljs-built_in">require</span>(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">value</span> <span class="hljs-operator">&gt;</span> <span class="hljs-number">0</span>, <span class="hljs-string">"Gas payment is required"</span>);

        <span class="hljs-comment">// Check if the sender owns the RWA token</span>
        <span class="hljs-built_in">require</span>(
            rwaToken.ownerOf(_collateralId) <span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>,
            <span class="hljs-string">"Not the owner of the RWA"</span>
        );

        <span class="hljs-comment">// Verify collateral value is sufficient</span>
        <span class="hljs-keyword">uint256</span> collateralValue <span class="hljs-operator">=</span> rwaOracle.getRWAValue(_collateralId);
        <span class="hljs-built_in">require</span>(
            (collateralValue <span class="hljs-operator">*</span> <span class="hljs-number">100</span>) <span class="hljs-operator">/</span> _amount <span class="hljs-operator">&gt;</span><span class="hljs-operator">=</span> LIQUIDATION_THRESHOLD,
            <span class="hljs-string">"Insufficient collateral"</span>
        );

        <span class="hljs-comment">// Prepare payload for cross-chain message</span>
        <span class="hljs-keyword">bytes</span> <span class="hljs-keyword">memory</span> payload <span class="hljs-operator">=</span> <span class="hljs-built_in">abi</span>.<span class="hljs-built_in">encode</span>(
            <span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>,
            _amount,
            _collateralId,
            _duration
        );

        <span class="hljs-comment">// Pay for gas on the source/destination chain</span>
        gasService.payNativeGasForContractCallWithToken{<span class="hljs-built_in">value</span>: <span class="hljs-built_in">msg</span>.<span class="hljs-built_in">value</span>}(
            <span class="hljs-keyword">address</span>(<span class="hljs-built_in">this</span>),
            destinationChain,
            destinationAddress,
            payload,
            lendingToken.symbol(),
            _amount,
            <span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>
        );

        <span class="hljs-comment">// Transfer collateral to this contract</span>
        rwaToken.transferFrom(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>, <span class="hljs-keyword">address</span>(<span class="hljs-built_in">this</span>), _collateralId);

        <span class="hljs-comment">// Transfer lending tokens to this contract</span>
        lendingToken.transferFrom(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>, <span class="hljs-keyword">address</span>(<span class="hljs-built_in">this</span>), _amount);

        <span class="hljs-comment">// Approve gateway to spend lending tokens</span>
        lendingToken.approve(<span class="hljs-keyword">address</span>(gateway), _amount);

        <span class="hljs-comment">// Initiate cross-chain call with token transfer</span>
        gateway().callContractWithToken(
            destinationChain,
            destinationAddress,
            payload,
            lendingToken.symbol(),
            _amount
        );
    }
}
</code></pre>
<p>In the code snippet above, you:</p>
<ul>
<li><p>Implemented verification of gas payment for cross-chain operation</p>
</li>
<li><p>Check ownership of the RWA token and ensure collateral value meets the liquidation threshold</p>
</li>
<li><p>Prepared the payload for cross-chain messages and paid for gas on the source/destination chain</p>
</li>
<li><p>Transferred RWA token (collateral) to the contract using the <code>transferFrom</code></p>
</li>
<li><p>Transferred lending tokens to the contract with the <code>transferFrom</code> method and approved the gateway to spending lending tokens by calling the <code>approve</code> method</p>
</li>
<li><p>Finally, Initiated the cross-chain call using <code>callContractWithToken</code></p>
</li>
</ul>
<h3 id="heading-create-repay-cross-chain-loan-function">Create Repay Cross-Chain Loan Function</h3>
<p>When a cross-chain loan is initiated and collateral is received, users need to repay the loan when they are ready. To achieve this, you will implement the loan repayment function.</p>
<p>In the contract, create a function named <code>repayCrossChainLoan</code> that accepts <code>_loanId</code>, <code>destinationChain</code>, and <code>destinationAddress</code> to repay the loan.</p>
<p>To do this, add the following code snippet below:</p>
<pre><code class="lang-solidity"><span class="hljs-comment">//...</span>

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">LendingPool</span> <span class="hljs-keyword">is</span> <span class="hljs-title">AxelarExecutable</span>, <span class="hljs-title">ReentrancyGuard</span>, <span class="hljs-title">Ownable</span> </span>{

    <span class="hljs-comment">//...</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">repayCrossChainLoan</span>(<span class="hljs-params">
        <span class="hljs-keyword">uint256</span> _loanId,
        <span class="hljs-keyword">string</span> <span class="hljs-keyword">memory</span> destinationChain,
        <span class="hljs-keyword">string</span> <span class="hljs-keyword">memory</span> destinationAddress
    </span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title"><span class="hljs-keyword">payable</span></span> <span class="hljs-title">nonReentrant</span> </span>{
        <span class="hljs-comment">// Ensure gas payment is provided</span>
        <span class="hljs-built_in">require</span>(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">value</span> <span class="hljs-operator">&gt;</span> <span class="hljs-number">0</span>, <span class="hljs-string">"Gas payment is required"</span>);

        <span class="hljs-comment">// Retrieve loan details</span>
        Loan <span class="hljs-keyword">storage</span> loan <span class="hljs-operator">=</span> loans[_loanId];

        <span class="hljs-comment">// Verify loan status and borrower</span>
        <span class="hljs-built_in">require</span>(loan.isActive, <span class="hljs-string">"Loan is not active"</span>);
        <span class="hljs-built_in">require</span>(loan.borrower <span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>, <span class="hljs-string">"Not the borrower"</span>);

        <span class="hljs-comment">// Calculate total repayment amount</span>
        <span class="hljs-keyword">uint256</span> interest <span class="hljs-operator">=</span> calculateInterest(
            loan.amount,
            loan.startTime,
            loan.duration
        );
        <span class="hljs-keyword">uint256</span> totalRepayment <span class="hljs-operator">=</span> loan.amount <span class="hljs-operator">+</span> interest;

        <span class="hljs-comment">// Transfer repayment amount from borrower</span>
        <span class="hljs-built_in">require</span>(
            lendingToken.transferFrom(
                <span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>,
                <span class="hljs-keyword">address</span>(<span class="hljs-built_in">this</span>),
                totalRepayment
            ),
            <span class="hljs-string">"Transfer failed"</span>
        );

        <span class="hljs-comment">// Mark loan as inactive</span>
        loan.isActive <span class="hljs-operator">=</span> <span class="hljs-literal">false</span>;

        <span class="hljs-comment">// Prepare payload for cross-chain message</span>
        <span class="hljs-keyword">bytes</span> <span class="hljs-keyword">memory</span> payload <span class="hljs-operator">=</span> <span class="hljs-built_in">abi</span>.<span class="hljs-built_in">encode</span>(
            _loanId,
            loan.collateralId,
            loan.borrower
        );

        <span class="hljs-comment">// Pay for gas on the destination chain</span>
        gasService.payNativeGasForContractCallWithToken{<span class="hljs-built_in">value</span>: <span class="hljs-built_in">msg</span>.<span class="hljs-built_in">value</span>}(
            <span class="hljs-keyword">address</span>(<span class="hljs-built_in">this</span>),
            destinationChain,
            destinationAddress,
            payload,
            lendingToken.symbol(),
            loan.amount,
            <span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>
        );

        <span class="hljs-comment">// Initiate cross-chain call to release collateral</span>
        gateway().callContract(sourceChain, sourceAddress, payload);

        <span class="hljs-comment">// Emit event for cross-chain loan repayment</span>
        <span class="hljs-keyword">emit</span> CrossChainLoanRepaid(_loanId);
    }
}
</code></pre>
<p>In the code snippet above, you:</p>
<ul>
<li><p>Implemented a check for gas payment to cover cross-chain operation costs</p>
</li>
<li><p>Retrieved and verified the loan details, ensuring the loan is active, and the caller is the borrower</p>
</li>
<li><p>Calculated the total repayment amount, including interest, using the <code>calculateInterest</code> function</p>
</li>
<li><p>Transferred the repayment amount from the borrower to the contract using <code>transferFrom</code></p>
</li>
<li><p>Marked the loan as inactive after successful repayment</p>
</li>
<li><p>Prepared a payload for the cross-chain message, including loan ID, collateral ID, and borrower address</p>
</li>
<li><p>Utilized the <code>gasService</code> to pay for gas on the source/destination chain, ensuring smooth cross-chain operation</p>
</li>
<li><p>Initiated a cross-chain call using <code>gateway.callContract</code> to trigger collateral release on the source chain</p>
</li>
<li><p>Emitted a <code>CrossChainLoanRepaid</code> event to log the successful repayment</p>
</li>
</ul>
<p>In the step above, you called the <code>calculateInterest</code> function, but it hasn't been implemented yet. Let’s do that in the following step.</p>
<h3 id="heading-implement-interest-calculation-function">Implement Interest Calculation Function</h3>
<p>This function calculates the interest for a loan based on the loan amount, start time, and duration.</p>
<pre><code class="lang-solidity"><span class="hljs-comment">//...</span>

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">LendingPool</span> <span class="hljs-keyword">is</span> <span class="hljs-title">AxelarExecutable</span>, <span class="hljs-title">ReentrancyGuard</span>, <span class="hljs-title">Ownable</span> </span>{

    <span class="hljs-comment">//...</span>

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">repayCrossChainLoan</span>(<span class="hljs-params"></span>)</span>{
    <span class="hljs-comment">//...</span>
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">calculateInterest</span>(<span class="hljs-params">
        <span class="hljs-keyword">uint256</span> _amount,
        <span class="hljs-keyword">uint256</span> _startTime,
        <span class="hljs-keyword">uint256</span> _duration
    </span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">view</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">uint256</span></span>) </span>{
        <span class="hljs-keyword">uint256</span> timeElapsed <span class="hljs-operator">=</span> <span class="hljs-built_in">block</span>.<span class="hljs-built_in">timestamp</span> <span class="hljs-operator">-</span> _startTime;

        <span class="hljs-comment">// Cap the time elapsed to the loan duration</span>
        <span class="hljs-keyword">if</span> (timeElapsed <span class="hljs-operator">&gt;</span> _duration) {
            timeElapsed <span class="hljs-operator">=</span> _duration;
        }

        <span class="hljs-comment">// Calculate interest: (amount * rate * time) / (365 days * 100 * 10^decimals)</span>
        <span class="hljs-comment">// For a 5% annual rate</span>
        <span class="hljs-keyword">uint256</span> interest <span class="hljs-operator">=</span> (_amount <span class="hljs-operator">*</span> <span class="hljs-number">5</span> <span class="hljs-operator">*</span> timeElapsed) <span class="hljs-operator">/</span> (<span class="hljs-number">365</span> <span class="hljs-literal">days</span> <span class="hljs-operator">*</span> <span class="hljs-number">100</span>);

        <span class="hljs-comment">// Adjust for token decimals (assuming 6 decimals for USDC)</span>
        <span class="hljs-keyword">return</span> interest <span class="hljs-operator">/</span> <span class="hljs-number">1e6</span>;
    }
}
</code></pre>
<p>In the code snippet above, you:</p>
<ul>
<li><p>Calculated the time elapsed since the loan started using <code>block.timestamp</code></p>
</li>
<li><p>Implemented a cap on the elapsed time to ensure it doesn't exceed the loan duration</p>
</li>
<li><p>Computed the interest using a formula that accounts for a 5% annual rate: <code>(amount * rate * time) / (365 days * 100)</code></p>
</li>
<li><p>Adjusted the calculated interest for token decimals, assuming 6 decimal places for USDC</p>
</li>
<li><p>Returned the final interest amount</p>
</li>
</ul>
<p>Next, you will implement the <code>_executeWithToken</code> to handle transferring the loan amount to the borrower.</p>
<h3 id="heading-create-the-executewithtoken-function">Create the <code>_executeWithToken</code> Function</h3>
<p>In this step, you'll implement the <code>_executeWithToken</code> function that manages cross-chain token transfers and loan creation on the destination chain. This function is essential for completing the cross-chain loan process.</p>
<pre><code class="lang-solidity"><span class="hljs-comment">//...</span>

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">LendingPool</span> <span class="hljs-keyword">is</span> <span class="hljs-title">AxelarExecutable</span>, <span class="hljs-title">ReentrancyGuard</span>, <span class="hljs-title">Ownable</span> </span>{

    <span class="hljs-comment">//...</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">_executeWithToken</span>(<span class="hljs-params">
        <span class="hljs-keyword">bytes32</span> commandId, 
        <span class="hljs-keyword">string</span> <span class="hljs-keyword">calldata</span> _sourceChain,
        <span class="hljs-keyword">string</span> <span class="hljs-keyword">calldata</span> _sourceAddress,
        <span class="hljs-keyword">bytes</span> <span class="hljs-keyword">calldata</span> payload,
        <span class="hljs-keyword">string</span> <span class="hljs-keyword">calldata</span> tokenSymbol,
        <span class="hljs-keyword">uint256</span>
    </span>) <span class="hljs-title"><span class="hljs-keyword">internal</span></span> <span class="hljs-title"><span class="hljs-keyword">override</span></span> </span>{
        <span class="hljs-comment">// Verify that the received token matches the lending token</span>
        <span class="hljs-built_in">require</span>(
            <span class="hljs-built_in">keccak256</span>(<span class="hljs-keyword">bytes</span>(tokenSymbol)) <span class="hljs-operator">=</span><span class="hljs-operator">=</span>
                <span class="hljs-built_in">keccak256</span>(<span class="hljs-keyword">bytes</span>(lendingToken.symbol())),
            <span class="hljs-string">"Invalid token"</span>
        );

        <span class="hljs-comment">// Store the source chain and address</span>
        sourceAddress <span class="hljs-operator">=</span> _sourceAddress;
        sourceChain <span class="hljs-operator">=</span> _sourceChain;

        <span class="hljs-comment">// Decode the payload to extract loan details</span>
        (
            <span class="hljs-keyword">address</span> borrower,
            <span class="hljs-keyword">uint256</span> _amount,
            <span class="hljs-keyword">uint256</span> _collateralId,
            <span class="hljs-keyword">uint256</span> _duration
        ) <span class="hljs-operator">=</span> <span class="hljs-built_in">abi</span>.<span class="hljs-built_in">decode</span>(payload, (<span class="hljs-keyword">address</span>, <span class="hljs-keyword">uint256</span>, <span class="hljs-keyword">uint256</span>, <span class="hljs-keyword">uint256</span>));

        <span class="hljs-comment">// Create a new loan internally</span>
        <span class="hljs-keyword">uint256</span> loanId <span class="hljs-operator">=</span> _createLoanInternal(
            borrower,
            _amount,
            _collateralId,
            _duration
        );

        <span class="hljs-comment">// Transfer the loan amount to the borrower</span>
        <span class="hljs-built_in">require</span>(lendingToken.<span class="hljs-built_in">transfer</span>(borrower, _amount), <span class="hljs-string">"Transfer failed"</span>);

        <span class="hljs-comment">// Emit an event for the created loan</span>
        <span class="hljs-keyword">emit</span> LoanCreated(loanId, borrower, _amount, _collateralId);
    }
}
</code></pre>
<p>In the code snippet above, you:</p>
<ul>
<li><p>Verified that the received token symbol matches the lending token symbol using <code>keccak256</code> hash comparison</p>
</li>
<li><p>Stored the source chain and address for future reference</p>
</li>
<li><p>Decoded the payload to extract loan details, including borrower address, loan amount, collateral ID, and loan duration</p>
</li>
<li><p>Created a new loan internally by calling the <code>_createLoanInternal</code> function with the extracted details</p>
</li>
<li><p>Transferred the loan amount to the borrower using the <code>transfer</code> method of the lending token</p>
</li>
<li><p>Emitted a <code>LoanCreated</code> event with the new loan's details</p>
</li>
</ul>
<p>In the implementation above, you called the <code>_createLoanInternal</code> function, but it hasn't been implemented yet. Let’s do that in the following step.</p>
<h3 id="heading-implement-createloaninternal-function">Implement <code>_createLoanInternal</code> Function</h3>
<p>The <code>_createLoanInternal</code> function is a helper function used to create a new loan with the internal type that returns the loan ID.</p>
<pre><code class="lang-solidity"><span class="hljs-comment">//...</span>

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">LendingPool</span> <span class="hljs-keyword">is</span> <span class="hljs-title">AxelarExecutable</span>, <span class="hljs-title">ReentrancyGuard</span>, <span class="hljs-title">Ownable</span> </span>{

    <span class="hljs-comment">//...</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">_createLoanInternal</span>(<span class="hljs-params">
        <span class="hljs-keyword">address</span> borrower,
        <span class="hljs-keyword">uint256</span> _amount,
        <span class="hljs-keyword">uint256</span> _collateralId,
        <span class="hljs-keyword">uint256</span> _duration
        </span>) <span class="hljs-title"><span class="hljs-keyword">internal</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">uint256</span></span>) </span>{
            <span class="hljs-comment">// Generate a new unique loan ID</span>
            <span class="hljs-keyword">uint256</span> loanId <span class="hljs-operator">=</span> nextLoanId<span class="hljs-operator">+</span><span class="hljs-operator">+</span>;

            <span class="hljs-comment">// Create a new Loan struct and store it in the loans mapping</span>
            loans[loanId] <span class="hljs-operator">=</span> Loan({
                amount: _amount,          <span class="hljs-comment">// The amount of the loan</span>
                collateralId: _collateralId,  <span class="hljs-comment">// ID of the collateral RWA token</span>
                startTime: <span class="hljs-built_in">block</span>.<span class="hljs-built_in">timestamp</span>,   <span class="hljs-comment">// Current time as the loan start time</span>
                duration: _duration,      <span class="hljs-comment">// Duration of the loan</span>
                borrower: borrower,       <span class="hljs-comment">// Address of the borrower</span>
                isActive: <span class="hljs-literal">true</span>            <span class="hljs-comment">// Mark the loan as active</span>
            });

            <span class="hljs-comment">// Return the newly created loan ID</span>
            <span class="hljs-keyword">return</span> loanId;
    }
}
</code></pre>
<p>In the code snippet above, you:</p>
<ul>
<li><p>Generated a new loan ID by incrementing the <code>nextLoanId</code> counter</p>
</li>
<li><p>Created a new <code>Loan</code> Struct with the provided parameters and additional details:</p>
<ul>
<li><p>Set the loan amount, collateral ID, and duration as provided</p>
</li>
<li><p>Recorded the current timestamp as the loan's start time</p>
</li>
<li><p>Set the borrower's address</p>
</li>
<li><p>Marked the loan as active</p>
</li>
</ul>
</li>
<li><p>Stored the new loan in the <code>loans</code> mapping using the generated loan ID</p>
</li>
<li><p>Returned the new loan ID</p>
</li>
</ul>
<p>You're almost done! It's great to see you've made it this far in the tutorial.</p>
<h3 id="heading-implement-execute-function-for-incoming-cross-chain-message">Implement <code>_execute</code> Function for Incoming Cross-chain Message</h3>
<p>This <code>_execute</code> function is automatically called by the <a target="_blank" href="https://docs.axelar.dev/dev/evm-relayer/">Axelar relayers</a>. It decodes the incoming payload and releases the collateral to the borrower on the source chain. Add the following code snippet to your contract.</p>
<pre><code class="lang-solidity"><span class="hljs-comment">//...</span>

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">LendingPool</span> <span class="hljs-keyword">is</span> <span class="hljs-title">AxelarExecutable</span>, <span class="hljs-title">ReentrancyGuard</span>, <span class="hljs-title">Ownable</span> </span>{

    <span class="hljs-comment">//...</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">_execute</span>(<span class="hljs-params">
        <span class="hljs-keyword">bytes32</span>,
        <span class="hljs-keyword">string</span> <span class="hljs-keyword">calldata</span>,
        <span class="hljs-keyword">string</span> <span class="hljs-keyword">calldata</span>,
        <span class="hljs-keyword">bytes</span> <span class="hljs-keyword">calldata</span> payload
    </span>) <span class="hljs-title"><span class="hljs-keyword">internal</span></span> <span class="hljs-title"><span class="hljs-keyword">override</span></span> </span>{
        (<span class="hljs-keyword">uint256</span> loanId, <span class="hljs-keyword">uint256</span> collateralId, <span class="hljs-keyword">address</span> borrower) <span class="hljs-operator">=</span> <span class="hljs-built_in">abi</span>.<span class="hljs-built_in">decode</span>(
            payload,
            (<span class="hljs-keyword">uint256</span>, <span class="hljs-keyword">uint256</span>, <span class="hljs-keyword">address</span>)
        );

        <span class="hljs-comment">// Release the collateral</span>
        rwaToken.transferFrom(<span class="hljs-keyword">address</span>(<span class="hljs-built_in">this</span>), borrower, collateralId);

        <span class="hljs-keyword">emit</span> CollateralReleased(loanId, collateralId, borrower);
    }
}
</code></pre>
<p>In the next step, you will test the contract using Fantom and Celo in this tutorial. However, feel free to use any network you prefer.</p>
<h2 id="heading-testing-the-lending-pool-contract">Testing the Lending Pool Contract</h2>
<p>You will test all the contracts you have built during this tutorial. To proceed, deploy and mint mock RWA tokens to the specified address.</p>
<h3 id="heading-deploy-mock-rwa-token">Deploy Mock RWA Token</h3>
<p>You will deploy the mock RWA Token on the Fantom network. Click on the <code>MockRWAToken.sol</code> file and go to the deploy section, as shown below.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728318354282/eaeec873-0c9e-44c7-8fb0-1a4b9a14ba0d.png" alt="Deploy Mock RWA Token" class="image--center mx-auto" /></p>
<p>Next, click <code>Transact</code> and specify your address.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728318741272/52fcb11d-f0d9-440c-9af8-6face742b8f5.png" alt="Next, click Transact and specify your address" class="image--center mx-auto" /></p>
<p>After deployment, you should be able to see the transaction chain similar to <a target="_blank" href="https://testnet.ftmscan.com/tx/0xcba609b0ee304fb77dc66117f7088070650966594049caa5cee95a41ec608c96">this</a>. in the next step you will mint tokens to your preferred address.</p>
<h3 id="heading-mint-rwa-tokens">Mint RWA tokens</h3>
<p>Scroll down to the deploy section on Remix, as shown below, to use the <code>safeMint</code> method. Mint the token to the specified address and click on <code>transact</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728319242378/f6092895-6a4e-47c0-b2f8-2824a22a7805.png" alt="Mint RWA tokens" class="image--center mx-auto" /></p>
<p>Check out the transaction <a target="_blank" href="https://testnet.ftmscan.com/tx/0x363f22e28dbe0b496957f4cf95dea6ec2a0236fc03753aad2a82ae9228702892">here</a>. Your transaction should look similar. To confirm, you can use the <code>balanceOf</code> method to verify, as shown below, where you can see the specified address has a balance of <code>1</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728319545132/22b64815-e35e-413b-b0c3-3178e4d90e40.png" alt="Check out the transaction here" class="image--center mx-auto" /></p>
<p>Next, you will deploy the RWAOracle contract, which simulates the Oracle price feed flow.</p>
<h3 id="heading-deploy-rwaoracle-contract">Deploy RWAOracle Contract</h3>
<p>To deploy the <code>RWAOracle</code> contract, navigate to the <code>RWAOracle.sol</code> file on the Fantom network and deploy the contract as shown below.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728320092689/96a80d29-2ca0-43ea-a348-91c5d1bcbaf2.png" alt="Deploy RWAOracle Contract" class="image--center mx-auto" /></p>
<p>After deploying, you should have a transaction on-chain similar to <a target="_blank" href="https://testnet.ftmscan.com/tx/0xffa082cf3277c5e552e0f6d65de92f4314cdc11f8599b4ff70d4448f16d020de">this</a> on the Fantom network.</p>
<h3 id="heading-set-rwa-token-value">Set RWA Token Value</h3>
<p>Next, set the RWA token value of the token you minted in the previous step. as shown below. The <code>_tokenId</code> is 0 (this is the first token minted), <code>_value</code> should be set to <code>20000000</code> which is 20×10^6.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728321425002/50ff5572-3c58-4b5a-8490-f13d17fe902c.png" alt="Set RWA Token Value" class="image--center mx-auto" /></p>
<p>After updating the RWA token value, you should have a transaction on-chain similar to <a target="_blank" href="https://testnet.ftmscan.com/tx/0x652a02d3c7983765a1edd66cfd063d4e0c64c1b21a831e5eb12b99495199af21">this</a>.</p>
<h3 id="heading-deploy-the-lending-pool-contract-on-the-fantom-testnet">Deploy the Lending Pool Contract on the Fantom Testnet</h3>
<p>Deploying the <code>LendingPool</code> contract is similar to how you deployed the other contracts earlier in this tutorial. Go to the lending pool contract file, click on the deploy section, and enter the following details as arguments for the contract. Then, click <code>transact</code> to deploy the contract on the Fantom testnet.</p>
<pre><code class="lang-bash">_initialOwner: 0x510e5EA32386B7C48C4DEEAC80e86859b5e2416C // Replace with your address
_gateway: 0x97837985Ec0494E7b9C71f5D3f9250188477ae14
_gasService: 0xbE406F0189A0B4cf3A05C286473D23791Dd44Cc6
_lendingToken: 0x75Cc4fDf1ee3E781C1A3Ee9151D5c6Ce34Cf5C61
_rwaToken: 0x1C84e5556301202e6f6d4826Be5e13265E48ee17
_rwaOracle: 0x57d6A23A9cD2A719A8da3e47b402c0E88AB6036E
</code></pre>
<p>The <code>_initialOwner</code> is the address of the account that minted the token. You can find the <code>_gateway</code> and <code>_gasService</code> addresses in the Axelar documentation <a target="_blank" href="https://docs.axelar.dev/resources/contract-addresses/testnet/">here</a>. This <code>lendingToken</code> is the <code>aUSDC</code> asset that the user will lend. For the Fantom network, scroll down on this <a target="_blank" href="https://docs.axelar.dev/resources/contract-addresses/testnet/">page</a> to the <code>Assets</code> section and copy the <a target="_blank" href="https://testnet.ftmscan.com/address/0x75Cc4fDf1ee3E781C1A3Ee9151D5c6Ce34Cf5C61">aUSDC contract</a> address on Fantom.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728322716138/83b238ac-dcbf-4c45-a0f1-4913af739e0e.png" alt="Transaction info" class="image--center mx-auto" /></p>
<p>You can find the transaction link <a target="_blank" href="https://testnet.ftmscan.com/tx/0xfb7d684279a293a220db636ff2a79579025b845ddf012d92491be4e856e9eb13">here</a>.</p>
<h3 id="heading-deploy-the-lending-pool-contract-on-the-celo-testnet">Deploy the Lending Pool Contract on the Celo Testnet</h3>
<p>Since this tutorial focuses on multichain lending, you will work with contracts on both the Fantom Testnet and the Celo Testnet. You will also deploy the contract on Celo before testing the cross-chain lending feature. Follow the same steps you used to deploy on the Fantom Testnet.</p>
<pre><code class="lang-bash">_initialOwner: 0x510e5EA32386B7C48C4DEEAC80e86859b5e2416C // Replace with your address
_gateway: 0xe432150cce91c13a887f7D836923d5597adD8E31
_gasService: 0xbE406F0189A0B4cf3A05C286473D23791Dd44Cc6
_lendingToken: 0x254d06f33bDc5b8ee05b2ea472107E300226659A
_rwaToken: 0x1C84e5556301202e6f6d4826Be5e13265E48ee17
_rwaOracle: 0x57d6A23A9cD2A719A8da3e47b402c0E88AB6036E
</code></pre>
<p>The <code>_initialOwner</code> is the address of the account that minted the token. You can find the <code>_gateway</code> and <code>_gasService</code> addresses in the Axelar documentation <a target="_blank" href="https://docs.axelar.dev/resources/contract-addresses/testnet/">here</a>. This <code>lendingToken</code> is the <code>aUSDC</code> asset that the user will lend. For the Celo test network, scroll down on this <a target="_blank" href="https://docs.axelar.dev/resources/contract-addresses/testnet/">page</a> to the <code>Assets</code> section and copy the <a target="_blank" href="https://alfajores.celoscan.io//address/0x254d06f33bDc5b8ee05b2ea472107E300226659A">aUSDC contract</a> address on Celo.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728322716138/83b238ac-dcbf-4c45-a0f1-4913af739e0e.png" alt="Transaction details" class="image--center mx-auto" /></p>
<p>You can find the transaction link <a target="_blank" href="https://alfajores.celoscan.io/tx/0xf43e724fc70e186cbdadc2732fa7fe752647bb736dfe097d22b0b824bb16ffb3">here</a>.</p>
<p>The next step is to initiate the cross-chain loan. Before doing that, you need to approve the lending pool contract address on the <code>MockRWAToken</code> contract on the Fantom testnet to allow the transfer of the asset from the user.</p>
<h3 id="heading-approve-the-lending-pool-contract-address-on-mockrwatoken-on-the-fantom-testnet">Approve the Lending Pool Contract Address on MockRWAToken on the Fantom Testnet</h3>
<p>Navigate to the MockRWAToken Deployment as shown below and click on approve, then specify the contract address.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728390800305/d5e31e7f-7bb2-4116-8aa6-e019b0cf3267.png" alt="Approve the Lending Pool Contract Address on MockRWAToken on the Fantom Testnet" class="image--center mx-auto" /></p>
<p>Please switch your network back to the Fantom testnet from Celo and then click the “transact” button.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728390815913/5e1aab16-f91d-4870-8051-4f6ae566e1cd.png" alt="Switch your network back to the Fantom testnet" class="image--center mx-auto" /></p>
<p>After approval is successful, you should have the transaction onchain similar to <a target="_blank" href="https://testnet.ftmscan.com/tx/0x20f845beccafa2d56ee31de48a97cdb616545417afded7e71719e23f77cf4dfb">this</a>.</p>
<h3 id="heading-approve-lending-pool-contract-to-spend-the-asset-to-be-borrowed">Approve Lending Pool Contract to Spend the Asset to Be Borrowed</h3>
<p>In the lending pool contract, there is an implementation inside the <code>initiateCrosschainLoan</code> function. You must approve the <code>LendingPool</code> contract address on the lending token contract (the asset you want to lend out).</p>
<blockquote>
<p>The asset you are using is aUSDC. If you don't have it, please request it on our Discord channel <a target="_blank" href="https://discord.com/invite/aRZ3Ra6f7D">here</a> by going to the faucet channel and asking for it for free.</p>
</blockquote>
<pre><code class="lang-solidity"><span class="hljs-comment">//...</span>

<span class="hljs-comment">// Transfer lending tokens to this contract</span>
lendingToken.transferFrom(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>, <span class="hljs-keyword">address</span>(<span class="hljs-built_in">this</span>), _amount);
</code></pre>
<p>Go to the Axelar documentation <a target="_blank" href="https://docs.axelar.dev/resources/contract-addresses/testnet/">here</a>, scroll down to the asset section, and click on the aUSDC contract address on Fantom.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728391963433/a25ee28d-ac03-414e-9562-8ff20c75f29c.png" alt="Go to the Axelar documentation here, scroll down to the asset section, and click on the aUSDC contract address on Fantom." class="image--center mx-auto" /></p>
<p>Go to the "Contract" tab, click on "Write Contract," and then connect your wallet by clicking on "Connect to Web3," as shown below.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728392248846/d871eb68-c6a8-4d6b-8504-089b04b728e8.png" alt="Go to the &quot;Contract&quot; tab, click on &quot;Write Contract,&quot; and then connect your wallet by clicking on &quot;Connect to Web3,&quot;" class="image--center mx-auto" /></p>
<p>Enter the lending pool contract address and the amount to be approved; for example, <code>0xE9D662dd2E4A479C2559bec1685b1BA4C4Ee24E1</code> and 50000000, which equals 50 × 10^6 since it is in aUSDC.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728392555773/a72132eb-d9bd-461b-b46e-9d98096345d2.png" alt="Enter the lending pool contract address and the amount to be approved" class="image--center mx-auto" /></p>
<p>Link to the approval transaction <a target="_blank" href="https://testnet.ftmscan.com/tx/0x6616c28ebac7bd12f161c56096c25a17afe2c1b9abf541ce23dc757ea67a2e54">here</a>.</p>
<p>One last thing before you call the <code>initiateCrosschain</code> function, you need to fund the destination contract so it can loan the user the required asset.</p>
<p>Here's how it works: If the user triggers the initiate cross-chain loan function from the source chain (Fantom) and reaches the destination chain (Celo), the <code>_executeWithToken</code> function in the contract will be triggered automatically. This is where you implement sending the asset the user wants to lend and fund the contract with the asset in the following step.</p>
<h3 id="heading-fund-the-destination-contract-with-the-asset-to-be-borrowed">Fund the Destination Contract with the Asset to be Borrowed</h3>
<p>To fund the contract on the destination chain (Celo), you can either request the asset on Axelar Discord to be sent directly to the contract address or transfer it from your account. Let's transfer it from an account as shown below.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728394057352/eead5ef7-1215-4fea-b9b8-0db1b803eb23.png" alt="Fund the Destination Contract with the Asset to be Borrowed" class="image--center mx-auto" /></p>
<p>Next, proceed to initiate the cross-chain loan. Here is the <a target="_blank" href="https://testnet.ftmscan.com/tx/0x73604bfec32361ff1d02ff4a4cac3f7bf98fd18d2da0fd180e546a8a8806734d">transaction link</a>.</p>
<h3 id="heading-call-initiatecrosschainloan-on-the-lending-pool-contract-on-fantom-network">Call initiateCrossChainLoan on the Lending Pool Contract on Fantom Network</h3>
<p>To initiate the cross-chain loan request, navigate to the lending pool deployment on Remix as shown below and enter the following details.</p>
<pre><code class="lang-bash">destinationChain: celo
destinationAddress: 0x36365FbCB839E309226d4f488310CcA3feDB91f4
_amount: 5000000 // 5 aUSDC
_collateralId: 0
_duration: 3600
</code></pre>
<p>Next, click “transact”.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728394563697/6187e26f-c293-4f84-b49d-b2649af6f2f4.png" alt="Call initiateCrossChainLoan on the Lending Pool Contract on Fantom Network" class="image--center mx-auto" /></p>
<p>Next, add gas value.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728395779005/35dc4f14-c964-42ec-8b5a-0485006a3513.png" alt="add gas value" class="image--center mx-auto" /></p>
<p>Transaction hash on the Fantom testnet is available <a target="_blank" href="https://testnet.ftmscan.com/tx/0x2ec0ee1f39499ec0163ccb9840e6b03cf9ec3f2906509616a3cebf32e95e1c4c">here</a>. You can also view it on Axelarscan <a target="_blank" href="https://testnet.axelarscan.io/gmp/0x2ec0ee1f39499ec0163ccb9840e6b03cf9ec3f2906509616a3cebf32e95e1c4c">here</a>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728396483014/407c74fd-1dd9-499b-909d-92038bada5a9.png" alt="Transaction details" class="image--center mx-auto" /></p>
<p>Congratulations! You have successfully initiated a cross-chain loan from the Fantom testnet to Celo. How does that feel? Great, right?</p>
<p>Next, you need to repay the loan, which is the typical process of lending.</p>
<h3 id="heading-call-repaycrosschainloan-on-lending-pool-contract-on-celo-tesnet">Call <code>repayCrossChainLoan</code> on Lending Pool Contract on Celo Tesnet</h3>
<p>One of the most interesting things about cross-chain activities or processes with Axelar GMP is that you can implement any custom functionality, like initiating a loan from one chain, repaying the loan from that same chain, or repaying the loan on the destination chain where the asset was used, and vice versa.</p>
<p>You must approve the <code>LendingPool</code> contract address to be able to transfer the amount the user wants to repay from the user's account to the address.</p>
<p>Go to the Axelar documentation <a target="_blank" href="https://docs.axelar.dev/resources/contract-addresses/testnet/">here</a>, scroll down to the asset section, and click on the aUSDC contract address on Celo.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728398299793/9f943f00-c940-416e-b8d5-d43b66ee0ab3.png" alt="Go to the Axelar documentation here, scroll down to the asset section, and click on the aUSDC contract address on Celo." class="image--center mx-auto" /></p>
<p>Go to the "Contract" tab, click on "Write Contract," and then connect your wallet by clicking on "Connect to Web3," as shown below.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728398481389/becc1784-f468-4197-8976-e0ee3ea535aa.png" alt="Go to the &quot;Contract&quot; tab, click on &quot;Write Contract,&quot;" class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728398626794/879d1aff-41aa-48b0-a7f7-fdfd89fd06d7.png" alt="connect your wallet by clicking on &quot;Connect to Web3" class="image--center mx-auto" /></p>
<p>Link to the <a target="_blank" href="https://alfajores.celoscan.io/tx/0x3ef1edaf88d04732e0641e657d2c93d249650242a9682facc6dcddcd22ee31a2">approval transaction</a>.</p>
<p>To repay the loan, navigate to the lending pool deployment contract section on Celo Remix and add the following details.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728397378503/e8653e45-2bc4-4096-8520-408ebb5419bd.png" alt="Select Lending pool contract deployed Celo" class="image--center mx-auto" /></p>
<pre><code class="lang-bash">_loadId: 0
destinationChain: Fantom
destinationAddress: 0xE9D662dd2E4A479C2559bec1685b1BA4C4Ee24E1
</code></pre>
<p>Next, add gas value.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728395779005/35dc4f14-c964-42ec-8b5a-0485006a3513.png" alt="Add gas value" class="image--center mx-auto" /></p>
<p>Please switch your network back to the Fantom testnet from Celo and then click the “transact” button.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728397817650/d267b8f0-f7b8-4537-a77a-525a13dcc2c1.png" alt="Please switch your network back to the Fantom testnet from Celo and then click the “transact” button." class="image--center mx-auto" /></p>
<p>Transaction hash on the Celo testnet is available <a target="_blank" href="https://alfajores.celoscan.io/tx/0xa9fba813e94b0cce486f34dccf84772d6e2e19d750ba32f5d571a4603506595d">here</a>. You can also view it on Axelarscan <a target="_blank" href="https://testnet.axelarscan.io/gmp/0xa9fba813e94b0cce486f34dccf84772d6e2e19d750ba32f5d571a4603506595d">here</a>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728399402743/af628243-183d-4a01-940d-902e4595c398.png" alt="Transaction details" class="image--center mx-auto" /></p>
<p>Woohoo! You have successfully repaid the loan and completed the entire process. If you check the transaction details page, you will notice the collateral has been released, as shown below.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728399563369/a66dfe74-b4a0-4abe-81f4-13b3d5266f29.png" alt="You have successfully repaid the loan and completed the entire process. If you check the transaction details page, you will notice the collateral has been released" class="image--center mx-auto" /></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In conclusion, integrating Axelar's General Message Passing (GMP) into a multichain Real-World Asset (RWA) lending platform offers a transformative approach to decentralized finance. The practical implementation of tokenized real-world assets, as demonstrated through the creation of smart contracts like <code>MockRWAToken</code>, <code>RWAOracle</code>, and <code>LendingPool</code>, showcases the potential for a more inclusive financial ecosystem.</p>
<p>This system empowers individuals, such as our hypothetical farmer Amani, to leverage their assets for financial growth, regardless of geographical or traditional banking limitations.</p>
<h2 id="heading-references">References</h2>
<ul>
<li><p><a target="_blank" href="https://docs.axelar.dev/dev/axelarjs/send-message"><strong>Axelar General Message Passing (GMP</strong></a><strong>)</strong></p>
</li>
<li><p><a target="_blank" href="https://www.coinbase.com/en-gb/learn/crypto-glossary/what-are-real-world-assets-rwa">Real-World Asset (RWA)</a></p>
</li>
<li><p><a target="_blank" href="https://docs.axelar.dev/resources/contract-addresses/testnet/">Testnet Asset</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Cross-Chain Memecoins With Axelar]]></title><description><![CDATA[The web3 industry has developed as much of a culture as it has a technology. A large part of that culture has been the rise of memecoins. Originally pioneered by Dogecoin, memecoins have emerged as a fun, lighthearted way for people to grow communiti...]]></description><link>https://blog.axelar.dev/cross-chain-memecoins-with-axelar</link><guid isPermaLink="true">https://blog.axelar.dev/cross-chain-memecoins-with-axelar</guid><category><![CDATA[Blockchain]]></category><category><![CDATA[Ethereum]]></category><category><![CDATA[Web3]]></category><category><![CDATA[axelar]]></category><category><![CDATA[Smart Contracts]]></category><category><![CDATA[software development]]></category><dc:creator><![CDATA[Ben Weinberg]]></dc:creator><pubDate>Mon, 30 Sep 2024 20:11:33 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1727727084817/28357ab8-f956-4f9c-9832-e60a79b27ae4.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The web3 industry has developed as much of a culture as it has a technology. A large part of that culture has been the rise of memecoins. Originally pioneered by <a target="_blank" href="https://dogecoin.com/">Dogecoin</a>, memecoins have emerged as a fun, lighthearted way for people to grow communities and try to make lucrative earnings in the process. </p>
<p>Memecoins have always been a part of the industry, but have recently been thrust into the spotlight these past few months with what people are calling <a target="_blank" href="https://unchainedcrypto.com/can-memecoin-mania-help-revive-ethereums-deflationary-dreams/">memecoin-mania</a>. Like any token on the market, the amount these memecoins can grow is limited to the number of holders it can reach. If the token is deployed on a single chain its available demand is limited to the community of that blockchain. With the emergence of Axelar’s <a target="_blank" href="https://www.axelar.network/its">Interchain Token Service</a> (ITS), memecoin creators now can create a natively cross-chain memecoin easier and quicker than has ever been done before. </p>
<p>ITS is a permissionless cross-chain token bridging service that allows users to deploy new cross-chain tokens and integrate live tokens to enable cross-chain functionality. It has a <a target="_blank" href="https://github.com/axelarnetwork/interchain-token-service/blob/main/contracts/InterchainTokenService.sol">smart-contract</a> deployed on nearly two dozen EVM chains that users can interact with to integrate and bridge their token. For a quicker integration, there is also a <a target="_blank" href="https://interchain.axelar.dev/">no-code solution</a> (<a target="_blank" href="https://testnet.interchain.axelar.dev/">testnet portal</a>) that users can integrate with as well. The rest of this blog will show you how to deploy and use your cross-chain memecoin both via the no-code portal and the programmatic solutions.</p>
<h1 id="heading-memecoin-with-its-portal">Memecoin With ITS Portal</h1>
<p>The most simple way to get your cross-chain memecoin deployed on multiple chains with built-in cross-chain functionality is through the portal. The portal is a free permissionless UI that interacts with the ITS contract. It gives you the option to deploy a fresh new token or integrate an existing token. Let’s go with the new token option. You can now fill out the token registration form. </p>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXddfdYdlnXHZ4B6ZulnVi6iBJeAqPcaayzK6dtllVSlFUTfME76h1_OCAG8l7Xm-N3VBEgxYSLAO7UXVgTVLDWlQWsjp067CO4cLA8p1GAaYsJ6mGu-8_8ehUpUddV_h2hXSPrH7wruV78bUQXE0pqCcos?key=Kh3ltSwi6kEfNPoGQn43IA" alt /></p>
<p>This requires the token’s name, symbol, decimal points, and total supply. While these parameters are relatively self-explanatory the <code>mintable</code> toggle is less so. The <code>mintable</code> toggle will allow you to set a “minter” address that can mint the token, since this is a memecoin it is best-practice that this token does not have any address that can mint additional tokens beyond the initial supply that is being minted on deployment. The salt is a unique value, which along with the deployer’s address (ITS itself in this case) will be used to generate the <code>interchainTokenId</code>. This ID is the unique value for your interchain token as far as ITS is concerned on-chain. There can technically be other tokens with the same name and symbol but the ID will need to be unique. </p>
<p>Once the token parameters have been filled in you can select which chains you want to deploy on (in addition to the chain you have your wallet currently connected to). </p>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXdrzZNbAUM6n3c7jSZifWyZAwjM4FiuNQMqXiG07Qp6mFvT1BJ8PkBAjH-Z9JUM7NeM0rgtEXWzXpOS_s7cag6YN53r5nkrF54yhMwiabRugrWfIVJCSEhaiS0SGd5xqIaKI1dbxooK_EE3ubICzX-zNPbF?key=Kh3ltSwi6kEfNPoGQn43IA" alt /></p>
<p>You have the option to deploy to any of these chains (and many others as well) simultaneously. For now, you can just deploy on Immutable to keep gas costs at a minimum. </p>
<p>Once the token is deployed, you will find yourself on the token detail page where you will see all the relevant info for the token as well as the chains the token is deployed to. On this page, you can also deploy your token to other chains that you did not initially deploy on. </p>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXctQYbOXZVTAt0Ps4nijgmG53e5HypsZ4RpjLIaLmuLQOy-VnJY494Kq1uCZYqulLLIvZoZ58oKdCnNKKOKK811L1fYEiaot1hg4YZmIYb06X2tzWP1p1Thf69opSca8E_WwPs_WBVOq2D798UruYabN5ta?key=Kh3ltSwi6kEfNPoGQn43IA" alt /></p>
<p>The token detail page shown above also provides a simple UI where you can interact with your token. For each chain your token is on with liquidity, you can send a cross-chain transfer between chains. In our case, the token only has liquidity on BNB. If the token was deployed with the <code>mintable</code> option toggle on, then you could also mint tokens. </p>
<p>The token that has been deployed from the portal is an <a target="_blank" href="https://github.com/axelarnetwork/interchain-token-service/blob/main/contracts/interchain-token/InterchainToken.sol">Interchain Token</a>. It contains all the standard functionality of an Open Zeppelin ERC20 with the addition of the <code>interchainTransfer()</code> functionality. Another added benefit is that the token is immediately <a target="_blank" href="https://testnet.bscscan.com/token/0x977554D912B6bA36520D570aA983a3765D4bB8c9#code">verified</a> on all the block explorers it is deployed to, which adds to the legitimacy of the memecoin in the eyes of the community.</p>
<h1 id="heading-minting">Minting</h1>
<p>In this example, since the token is not <code>mintable</code> the 1 Billion tokens that were minted upon creation are all that will ever be created. However, the token that is deployed still does have a <code>mint()</code> function. The reason for this is that when tokens are bridged between chains they are burned on the source chain and minted on the destination chain. If the token has no official minter then the only contract that can mint the token is the <a target="_blank" href="https://etherscan.io/address/0xB5FB4BE02232B1bBA4dC8f81dc24C26980dE9e3C">ITS contract</a> itself. This does not pose any security threat for your memecoin to mint an infinite new supply of new tokens as the mint() function only exists to bridge the existing supply of tokens between chains, rather than to create fresh new tokens. </p>
<h1 id="heading-adding-value">Adding Value</h1>
<p>Now that your token is deployed successfully, you can create a liquidity pool for it on a <a target="_blank" href="https://www.coinbase.com/en-ca/learn/crypto-basics/what-is-a-dex">Decentralized Exchange (DEX)</a> so that it can receive some actual value. This can be done on any number of exchanges, we will use <a target="_blank" href="https://pancakeswap.finance/">Pancake Swap</a>.</p>
<p>DEXs allow users to swap tokens. They leverage pools of assets to generate a value for each token. For however many pools are in a given token the DEX uses a <a target="_blank" href="https://dev.to/learnweb3/how-do-dexs-work-understand-uniswap-v1-by-deep-diving-into-the-math-and-code-learn-the-xyk-amm-curve-46hb">formula</a> to calculate what each asset in the pool can be traded for. </p>
<p>For the memecoin all you have to do to give your token a starting value is to create a pool for your token alongside another token that already has an inherit value. Once you have funded that pool with the two tokens your memecoin will be given a value relative to the amount of liquidity supplied to the pool for the two tokens. </p>
<p>The memecoin so far is deployed on BNB and Immutable. Let’s create a liquidity pool on Pancake Swap’s BNB instance for the CCM memecoin with Binance’s native BNB token. </p>
<p>To do this go to the <a target="_blank" href="https://pancakeswap.finance/add/tBNB/0x8d008B313C1d6C7fE2982F62d32Da7507cF43551/2500?chain=bscTestnet">Add Liquidity</a> page on Pancake Swap and ensure that your wallet is pointed to BNB’s testnet. You can then create a new pool for tBNB and your ITS token’s address by importing your ITS token on the Pancake Swap UI</p>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXcQYDN4VxfW2-HYCB-mptad5Dj124Csp_3C_GkNMCfESLBGXqY_OXnsZ7CvW3wbbaH5aLEwmg9srrfVXQs0MqAPmZl7tTER5EAk8rq8qq7x2PhPv1-8UPGnRO4-V6mLM4TBXW_C7wB8JtC_EbOjF3_ubD94?key=Kh3ltSwi6kEfNPoGQn43IA" alt /></p>
<p>Next, you can deposit funds into the new pool. You can deposit however many of the memecoins and BNB you want to the pool, depending on what you want the price of the memecoin to be. For this demo, we will deposit 75% of all minted memecoins to the pool along with 0.5 BNB. The DEX UI will show you the value of your memecoin relative to BNB before creating the token pair.</p>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXdL6Npxabw06vrfOEaz-65F_Z_sVG8giAoDt0M6miDKdC_o1nAvwBXppHHv9QMwnT9mXydmg8HpM9iOB0m0UVUDcUasPwd-ixk8rXEcznNhkZq3as_IMabrwPyTFszHpHxb8IFmKNCkDNurWw1aU2iPda9u?key=Kh3ltSwi6kEfNPoGQn43IA" alt /></p>
<p>You can then submit the <a target="_blank" href="https://testnet.bscscan.com/tx/0xded2da7e83f56baecc8782c2574d50fab1ab605345d0f5c71edf3cd4c0aebf40">transaction</a> to create your <a target="_blank" href="https://testnet.bscscan.com/token/0x7861b84b4b0fe5b9d35fe0ea44a5432f75c44777">pair</a>!</p>
<p>Once the transaction executes you will be able to swap your token on PancakeSwap for other tokens so that it has a real value.</p>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXdIy6QDAC17JhcW77xN60Vy1qYSfYuWCTn7R1io9DQmoPFMdox3qxCOsvvfYWywiuZWwyQKgoqFNmNryEh2Djnxyutk3bq6IuvFQZ1Aw0uJ6IR-9ot1G61ce_XDYnU-gcFcK4J3FiXwbNnNZcPHmzILgEjp?key=Kh3ltSwi6kEfNPoGQn43IA" alt /></p>
<p>Notice the CCM asset does not have an image being picked up by the DEX. This is beyond the scope of this tutorial but to do so you could add your token metadata to <a target="_blank" href="https://github.com/trustwallet/assets">TrustWallet</a>, which many DEX’s pull from to render token metadata.</p>
<h2 id="heading-cross-chain-token">Cross-Chain Token</h2>
<p>Great! At this point, you have deployed an ITS-compatible token, which exists on both BNB and Immutable. The real magic though is the ability to send these tokens seamlessly between the two chains (and more chains as the CCM token is onboarded to new chains). </p>
<p>Stepping back into the <a target="_blank" href="https://testnet.interchain.axelar.dev/">ITS Portal</a> you will see the token has been minted on the BNB home chain but there is a supply of 0 on the Immutable chain. The portal offers a simple one-click transaction experience where users can simply input the amount of tokens they want to transfer. Simply click the <code>transfer</code> button, which will allow you to transfer to any chain your token is deployed to. This will trigger a cross-chain <a target="_blank" href="https://testnet.axelarscan.io/gmp/0x91b5cce60f2657e46993293f82c2b41b4c56f17aacdc8161a3a6639fc4962815">transaction</a> that can be viewed on the <a target="_blank" href="https://axelarscan.io/">Axelarscan block explorer</a>. When the transfer completes, the tokens will be burned on BNB and <strong>a</strong>utomatically minted on the Immutable chain. You’ve just migrated your tokens seamlessly!</p>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXd-yObjn7a8ZjORUEf9puMjzK1vsSG8R6ew9RUATV2v0xhhjc6t86E1ZK9diVdTGdjIzxwAarCvKaaP7kww7gYVrBGz7w_rBybk0KwLvZmcXx5AAO1SHVdsM_Fk0IX2ksWCbRq3nj-Wr-FpW0pkLmmUgzit?key=Kh3ltSwi6kEfNPoGQn43IA" alt /></p>
<p>Now that the token is on Immutable you can create a pool on a DEX there so that the token has a value on that chain as well. This adds more overall liquidity to your token as it will now be exposed to the communities on more than just the BNB chain, thus providing more opportunity for memecoin to increase in value. </p>
<h3 id="heading-adding-value-on-immutable">Adding Value on Immutable</h3>
<p>Similar steps can be taken to give the token value on Immutable as you did on BNB. </p>
<p>For Immutable you will need to use the <a target="_blank" href="https://quickswap.exchange/">Quickswap DEX</a> to create a pool for the CMM token’s instance there. </p>
<p>This will follow a very similar flow to the path you used on PancakeSwap. </p>
<ul>
<li><p>Go to the <a target="_blank" href="https://quickswap.exchange/#/pools">pools page</a></p>
</li>
<li><p>Import your memecoin by pasting in the address</p>
</li>
<li><p>Select your fee tier</p>
</li>
<li><p>Select your token’s price range</p>
</li>
<li><p>Deposit your memecoin as long as an additional collateral (you can simply do IMX for Immutable) into the pool.</p>
</li>
</ul>
<p>When you press the preview button, your pool should look as follows</p>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXcHTifoCA2sZ7SY09qWZHPoWzq6zHmVSIpj_F1Un6YJtXp5lrC_uw6qytdHMM9KZV9Kh3Dq_qZcxzyp844MBdRxKwaYq-iuySUs0n3UmCDXcCzHuWp3MFctQOa59DUDOzAKqSJKSZVM8LC-wuEYaG_Cu4zi?key=Kh3ltSwi6kEfNPoGQn43IA" alt /></p>
<p>Great! At this point, you should now have a fully functioning pool on the Immutable blockchain. Your memecoin is now operational and accruing value on both BNB and Immutable.</p>
<h3 id="heading-why-this-matters">Why this matters</h3>
<p>Now that your users can interact with your tokens on multiple blockchains the amount of users you can reach and liquidity that can be injected into your memecoin significantly increases with each new blockchain you deploy your token to. This can be as strategic as being an early memecoin adopter of a hot new layer two or reaching the large user base of more established blockchain ecosystems. </p>
<p>With your token operating on dexes across multiple blockchains the opportunity for lucrative arbitrage opportunities becomes available for your community. Your community can do the heavy lifting and earn substantial rewards in the process to ensure the price of your memecoin is consistent across chains. More creative teams can try to gamify this process to make their memecoin fun and unique compared to other non-cross-chain memecoins on the market. </p>
<h1 id="heading-memecoin-programmatically">Memecoin Programmatically</h1>
<p>When going through the ITS Portal the token that will be created is an <a target="_blank" href="https://github.com/axelarnetwork/interchain-token-service/blob/main/contracts/interchain-token/InterchainToken.sol">Interchain Token</a>. For teams that want to have some more customization to the functionality of their token, they will need to integrate with the <a target="_blank" href="https://github.com/axelarnetwork/interchain-token-service/blob/main/contracts/InterchainTokenService.sol">ITS contract</a> programmatically. To do this you will need to call the <code>deployTokenManager()</code> function <a target="_blank" href="https://github.com/axelarnetwork/interchain-token-service/blob/main/contracts/InterchainTokenService.sol#L286">exposed</a> by the ITS contract. </p>
<p>Before integrating with ITS the ERC20 memecoin must be deployed programmatically. This can be done via a <a target="_blank" href="https://book.getfoundry.sh/forge/">foundry</a>-based local repository or through a simple ERC20 deployment on <a target="_blank" href="https://remix.ethereum.org/#lang=en&amp;optimize=false&amp;runs=200&amp;evmVersion=null&amp;version=soljson-v0.8.22+commit.4fc1097e.js">Remix</a>. Once the token is deployed and has an address you can integrate it with the ITS contract by calling the aforementioned <code>deployTokenManager()</code> function. </p>
<p>To call this function you need to pass in several parameters.</p>
<ol>
<li><p><code>Salt</code>: A unique identifier for your tokens deployment</p>
<ul>
<li>This will be used to generate the <a target="_blank" href="https://github.com/axelarnetwork/interchain-token-service/blob/main/contracts/InterchainTokenService.sol#L228">interchainTokenId</a>. </li>
</ul>
</li>
<li><p><code>DestinationChain</code>: The chain you are integrating your token on</p>
<ul>
<li>If you’re not making a cross-chain call this can be an empty string.</li>
</ul>
</li>
<li><p><code>TokenManagerType</code>:</p>
<ul>
<li>The type of token manager to be deployed. There are several types of managers, the recommended one for most integrations is the <code>mint</code>/<code>burn</code> token manager. More on Token Managers can be found <a target="_blank" href="https://docs.axelar.dev/dev/send-tokens/interchain-tokens/token-manager/">here</a>.</li>
</ul>
</li>
<li><p><code>Params</code>:</p>
<ul>
<li>This is an encoding of your token’s <code>operator</code> and <code>tokenAddress</code>.</li>
</ul>
</li>
<li><p><code>GasValue</code>: </p>
<ul>
<li>This is the amount of gas to pay for your cross-chain deployment. As with <code>DestinationChain</code> if you are deploying your token manager on the same chain (i.e. not a cross-chain call), this can be set to 0. </li>
</ul>
</li>
</ol>
<p>Once this function is called you will be returned your <code>interchainTokenId</code></p>
<h3 id="heading-interchaintokenid">InterchainTokenId</h3>
<p>The <code>interchainTokenId</code> is the unique identifier for your ITS token across all the different chains it is integrated with. It is how ITS will know which token across all chains your token corresponds to when burning it on one chain and minting on another. </p>
<p>This ID is created by hashing the address of the <code>sender</code> of the Token Manager deployer with the <code>salt</code> used in the Token Manager deployment. For this reason, it is critical to use the same deployer address across all ITS integrations so that the <code>interchainTokenId</code> is consistent across all chains for your token. </p>
<h3 id="heading-interchain-transfer">Interchain Transfer</h3>
<p>Once your token is integrated and you have an <code>interchainTokenId</code> across several chains you can call the <code>interchainTransfer()</code> function to send cross-chain transactions for your token. This function is <a target="_blank" href="https://github.com/axelarnetwork/interchain-token-service/blob/main/contracts/InterchainTokenService.sol#L456">defined</a> on the ITS contract but can also be added to your token if you prefer to send cross-chain transfers from the token itself. </p>
<p>It takes several parameters including;</p>
<ol>
<li><p><code>TokenId</code>: This is the <code>interchainTokenId</code> you received when you deployed the token manager.</p>
</li>
<li><p><code>DestinationChain</code>: Name of the chain you are sending the token to.</p>
</li>
<li><p><code>DestinationAddress</code>: Receiving address on the destination chain.</p>
</li>
<li><p><code>Amount</code>: Amount of the tokens you are sending.</p>
</li>
<li><p><code>Metadata</code>: (optional) Executable data to be sent alongside your token. Most likely not needed for more basic memecoin initiatives.</p>
</li>
<li><p><code>GasValue</code>: Amount of gas you are sending to pay for the transaction. It should match the <code>msg.value</code> you're sending with the token transfer. </p>
</li>
</ol>
<p>Once this function is called you should be able to see the cross-chain transaction be sent on <a target="_blank" href="http://axelarscan.io">Axelarscan</a>.</p>
<p>For a more detailed example of how to integrate and send a custom cross-chain transfer, you can visit this <a target="_blank" href="https://github.com/axelarnetwork/axelar-examples/tree/main/examples/evm/its-custom-token">example</a>.</p>
<h1 id="heading-whats-next">What’s Next?</h1>
<p>Now that your memecoin is successfully deployed and bridgeable between different blockchains you can whitelist your token to <a target="_blank" href="https://www.squidrouter.com/">Squid Router</a>. Squid provides an easy-to-use cross-chain swapping experience for your token, it also plugs into many popular wallets such as Meta Mask. By whitelisting on Squid your users will have a one-click bridging experience.</p>
<p>In this blog, you went over how to deploy a cross-chain token both with the <a target="_blank" href="https://interchain.axelar.dev/">ITS Portal</a> and programmatically by interacting with the <a target="_blank" href="https://github.com/axelarnetwork/interchain-token-service/blob/main/contracts/InterchainTokenService.sol">ITS contract</a> directly. You interacted with DEXes on multiple blockchains to assign a value to the token which on mainnet could prevent exciting arbitrage opportunities for users. </p>
<p>What may have once been an ordinary memecoin on one blockchain is now a unique cross-chai compatible memecoin with the ability to access any user in web3.</p>
<p>For more exciting technical tutorials pushing the limits of what can be done cross-chain check out the <a target="_blank" href="https://blog.axelar.dev/?source=top_nav_blog_home">Axelar Developer Blog</a> and the <a target="_blank" href="https://github.com/axelarnetwork/axelar-examples/tree/main">Axelar Examples</a> repository. For more ITS tutorials check out the <a target="_blank" href="https://docs.axelar.dev/dev/send-tokens/interchain-tokens/developer-guides/programmatically-create-a-token/">developer guides</a> on the Axelar docs.</p>
]]></content:encoded></item><item><title><![CDATA[Interchain Amplifier on Mainnet & Foundry GMP with ITS – Sept Dev Update 🏗️]]></title><description><![CDATA[Welcome to the September 2024 Axelar Developer Newsletter!
About Axelar: Axelar is the Web3 interoperability platform, delivering the shortest path to scale: an open stack to connect all blockchains. Adopters include Uniswap, Microsoft, and dozens of...]]></description><link>https://blog.axelar.dev/interchain-amplifier-foundry-gmp-update-axelar-sept-dev-update</link><guid isPermaLink="true">https://blog.axelar.dev/interchain-amplifier-foundry-gmp-update-axelar-sept-dev-update</guid><category><![CDATA[axelar]]></category><category><![CDATA[Blockchain]]></category><category><![CDATA[Web3]]></category><category><![CDATA[foundry]]></category><category><![CDATA[software development]]></category><category><![CDATA[Smart Contracts]]></category><dc:creator><![CDATA[Idris Olubisi]]></dc:creator><pubDate>Mon, 30 Sep 2024 16:00:27 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1727643126804/39ae9d61-f727-461f-affe-b470ac42861e.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Welcome to the September 2024 Axelar Developer Newsletter!</p>
<p><strong>About Axelar:</strong> Axelar is the Web3 interoperability platform, delivering the shortest path to scale: an open stack to connect all blockchains. Adopters include Uniswap, Microsoft, and dozens of natively multichain startups, building applications to reach all blockchain users at once – <a target="_blank" href="https://twitter.com/bigjaymes_/status/1775223859173552139?s=20">10X as many active users</a> as the leading Web3 application environment.</p>
<p>This month, we're excited to share major milestones in our journey to enhance cross-chain interoperability, including the <a target="_blank" href="https://docs.axelar.dev/dev/amplifier/introduction/">Interchain Amplifier</a> on mainnet with integrations forthcoming and significant updates to our developer tools.</p>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXeWQrFn3144b3SYJ6pNAVQwdZnuGUVciwqcmeAq5rqgK8leHEJFVs8ubgD2QEBzjFVnzhufC5oEOnuqFRFY3ucTnyHYFV3TbGAEZgnhXg7v8t6w6sfXcgJwjd6cp50RvZGVboRR31JaXDlnkwSREdNWv-M?key=P0rO7SeD64db5hTEaGGFXg" alt /></p>
<h2 id="heading-axelar-network-beyond-what-you-thought-possible"><strong>🆙</strong> Axelar Network: Beyond What You Thought Possible</h2>
<p><strong>📅</strong> Save the Date: October 3, 2024</p>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXdtls672uBb_Vv0dv3JkXD6vOK9Tu4ylxvlHIUZOhF0aYpWsav-aP02YLbNEOXUSDwvWaJZfc60Bc3Dgdwx6pf3Szkll8L-ogHF_AM7w3Ny7NnUk1aOS6wwK7FSo46tFP0qnKIp9gZhxZ2SwL80ge3Vx-VA?key=P0rO7SeD64db5hTEaGGFXg" alt /></p>
<p>We're preparing for a significant announcement that will redefine what's possible with blockchain interoperability. Mark your calendars for October 3, 2024, and stay tuned for an exciting reveal! <a target="_blank" href="https://x.com/axelar/status/1839037156112613614">Learn more</a>.</p>
<h2 id="heading-interchain-amplifier-deployed-on-mainnet">🔬 Interchain Amplifier Deployed on Mainnet</h2>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXcS9VMRupkyhPH5UX5yeOUFCSnmPV59xM5UD0TCuYzBMhU4jqit8wjPQRtk_UNEdHAIHFCUuk1zOIyW47BlckJbYUfUW19yAaBAhQuAY93IuHi6eVScSCVQ6GZ4tvqtzaSCfRAbW8FGuRqZNwnrL6ipJv8_?key=P0rO7SeD64db5hTEaGGFXg" alt /></p>
<p>We are super pumped to announce that the Interchain Amplifier service has been successfully deployed and instantiated on the mainnet. This deployment lays the foundation for enhanced cross-chain interoperability within the Axelar network.</p>
<h3 id="heading-what-the-interchain-amplifier-offers">What the Interchain Amplifier Offers</h3>
<ul>
<li><p>Seamless Connection of Diverse Blockchain Consensus Engines</p>
</li>
<li><p>Integration with Traditional Off-Chain Systems</p>
</li>
<li><p>Minimal Developer Overhead</p>
</li>
</ul>
<h3 id="heading-key-components-include">Key Components Include</h3>
<ul>
<li><p>On-Chain Message Router</p>
</li>
<li><p>Gateways</p>
</li>
<li><p>CosmWasm Methods for Bidirectional Messaging</p>
</li>
</ul>
<h3 id="heading-current-status">Current Status</h3>
<ul>
<li><p><strong>Deployment Completed</strong>: The Amplifier infrastructure is live on the mainnet.</p>
</li>
<li><p><strong>Integrations Pending:</strong> Active integrations with various chains are being developed and rigorously tested on the testnet to ensure stability and reliability before their mainnet deployment.</p>
</li>
</ul>
<h3 id="heading-what-this-means-for-you">What This Means for You</h3>
<p>Gain unprecedented flexibility in building cross-chain applications with reduced complexity. As integrations are finalized and proven on testnet, they will be seamlessly proposed and rolled out on mainnet, expanding your opportunities to leverage diverse blockchain ecosystems.</p>
<p>Curious? Get started with Amplifier <a target="_blank" href="https://docs.axelar.dev/dev/amplifier/introduction">here</a>.</p>
<h2 id="heading-foundry-axelar-gmp-example-now-supports-interchain-token-service-its-integration">🛠️ Foundry Axelar GMP Example Now Supports Interchain Token Service (ITS) Integration</h2>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXcArY__tvlylh58SjDDPerKuSqTYYMLMSg-0HRyeobeyn5TkL77rIpsRHpgR7nsyn7vW-tf6jrVT-GoELMfWn3-2EXcBk32vd_Ub9tcNGKte5IYXR9JzTxF7mnzTgAbs5Is5j9UeR3TV6gFfa82dLt9Q4hY?key=P0rO7SeD64db5hTEaGGFXg" alt /></p>
<p>We're excited to announce that our <a target="_blank" href="https://github.com/axelarnetwork/foundry-axelar-gmp-example"><strong>Foundry Axelar General Message Passing (GMP) Example</strong></a> repository now supports the <strong>Interchain Token Service (ITS)</strong>, making it easier than ever to build cross-chain applications.</p>
<h3 id="heading-what-is-the-interchain-token-service-its"><strong>What is the Interchain Token Service (ITS)?</strong></h3>
<p>Axelar's Interchain Token Service (ITS) is a solution that allows developers to create and manage tokens that operate seamlessly across multiple blockchain networks. With ITS, you can deploy tokens that are natively cross-chain, eliminating the complexities of manually bridging and wrapping tokens.</p>
<h3 id="heading-whats-new-in-the-repository"><strong>What's New in the Repository?</strong></h3>
<ul>
<li><p><strong>Interchain Token Example:</strong> Learn how to deploy a brand-new interchain token using ITS.</p>
</li>
<li><p><strong>Canonical Token Deployment Example:</strong> Discover how to deploy a canonical token that serves as a single source of truth across chains.</p>
</li>
<li><p><strong>Interchain Custom Token Example:</strong> Explore how to create custom tokens with interchain functionality.</p>
</li>
</ul>
<h3 id="heading-why-this-matters-to-you"><strong>Why This Matters to You</strong></h3>
<ul>
<li><p><strong>Simplify Multichain Token Development:</strong> Create tokens that work across different blockchain networks without juggling multiple codebases.</p>
</li>
<li><p><strong>Streamline Cross-Chain Interactions:</strong> Utilize Axelar's General Message Passing to interact effortlessly with contracts on other chains.</p>
</li>
<li><p><strong>Accelerate Your Development Process:</strong> Leverage ready-made examples and scripts to speed up building your cross-chain applications.</p>
</li>
</ul>
<p>Check out the updated repository here: <a target="_blank" href="https://github.com/axelarnetwork/foundry-axelar-gmp-example">Foundry Axelar GMP Example</a>.</p>
<h2 id="heading-new-tutorials-docs-and-more">📚 New Tutorials, Docs, and More</h2>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXdyXeulpMt_FlHbGfN0fka_7zzX_Mz-AMjIc932Ce-dqgjbh--mU-ctrwJ3mQFOXHKsb17kOzL0z7xDCyk5PsUpm6zI_9PWSA7ID-Tu4QmtRbOXh6tI7z6s7xhoOvlDK813d4SLyyqrziZK8AInOyIgG16B?key=P0rO7SeD64db5hTEaGGFXg" alt /></p>
<p>We've just published several relevant technical articles and documentation updates.</p>
<h3 id="heading-amplifier">Amplifier</h3>
<ul>
<li><p><a target="_blank" href="https://docs.axelar.dev/dev/amplifier/roadmap/">Amplifier Roadmap</a><strong>:</strong> The Interchain Amplifier will be gradually rolled out in six phases, unlocking features like CosmWasm smart contract support, chain onboarding, relayer functionality, and ITS token transfers on the Axelar network.</p>
</li>
<li><p><a target="_blank" href="https://docs.axelar.dev/validator/amplifier/verifier-security-expectations">Verifier Security Expectations</a><strong>:</strong> Learn about the security expectations for verifiers in the Axelar network, including running full nodes, maintaining uptime, rotating keys, pulling rewards, supporting trustworthy chains, and participating in security drills and escalations.</p>
</li>
<li><p><a target="_blank" href="https://docs.axelar.dev/dev/amplifier/add-rewards">Add rewards for Amplifier chain integrators</a>: Learn how to add funds to the rewards pool of an Amplifier-integrated chain.</p>
</li>
</ul>
<h3 id="heading-its">ITS</h3>
<ul>
<li><a target="_blank" href="https://docs.axelar.dev/dev/send-tokens/interchain-tokens/token-manager/">Token Manager Types</a>: Learn how Token Manager contracts facilitate the connection between your interchain token and the Interchain Token Service (ITS).</li>
</ul>
<h2 id="heading-catch-up-on-any-events-you-missed">🎤 Catch up on any events you missed</h2>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXcRIC_cksh0ISuhB0xGrreQ9adryrcTCxk4suc2Bv4KercbIxF0fWNwTxImmmITIq2atotJFJc9nSy_lSz_QNdY5TjyBsXinlYEP8pknZoFdEA1icDKgCpelDjs-rSW8g_6BzYiFNUlUrs-htKXRuHnbx3b?key=P0rO7SeD64db5hTEaGGFXg" alt /></p>
<p>Did you miss our recent talks? Here are some highlights:</p>
<ul>
<li><p><a target="_blank" href="https://www.youtube.com/live/_IgpqXDf4Lg?si=Q_QOcDcDz82Lz_PG">A Hitchhiker’s Guide to Multichain dApps</a></p>
</li>
<li><p><a target="_blank" href="https://youtu.be/v11GCdJ5ELE?t=3">Build a Multichain RWA Lending Platform</a></p>
</li>
<li><p><a target="_blank" href="https://www.youtube.com/live/5loZw3iDOuo?si=-ZlXY3pv7YpWQUpA">Building a Multichain Tax Contract with ITS</a> </p>
</li>
</ul>
<h2 id="heading-stay-connected"><strong>📌 Stay Connected</strong></h2>
<p>We have a lot more planned for the upcoming months, so you won’t want to miss out.</p>
<ul>
<li><p><strong>🐦 Follow us on</strong> <a target="_blank" href="https://x.com/axelarnetwork"><strong>X (Twitter)</strong></a> to stay updated on upcoming developer content and live events.</p>
</li>
<li><p><strong>💬 Join our</strong> <a target="_blank" href="https://discord.com/invite/aRZ3Ra6f7D"><strong>Discord community</strong></a> for real-time discussions and support.</p>
</li>
<li><p><strong>📰 Subscribe to the</strong> <a target="_blank" href="https://blog.axelar.dev/newsletter"><strong>Axelar Devblog</strong></a> to stay up to date on the latest Axelar news.</p>
</li>
</ul>
<hr />
<p>Thank you for being a part of the Axelar community. We can't wait to see what you'll build next!</p>
]]></content:encoded></item><item><title><![CDATA[Cross-Chain Governance with OpenZeppelin Governor and Axelar]]></title><description><![CDATA[Multichain applications are becoming the new norm, but managing governance across these networks remains a significant challenge. For decentralized applications (dApps) with deployments on multiple blockchains, ensuring an easy governance processes w...]]></description><link>https://blog.axelar.dev/cross-chain-governance-with-openzeppelin-governor-and-axelar</link><guid isPermaLink="true">https://blog.axelar.dev/cross-chain-governance-with-openzeppelin-governor-and-axelar</guid><category><![CDATA[Cross-chain]]></category><category><![CDATA[axelar]]></category><category><![CDATA[openzeppelin]]></category><category><![CDATA[Smart Contracts]]></category><category><![CDATA[Blockchain]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Solidity]]></category><category><![CDATA[software development]]></category><dc:creator><![CDATA[Idris Olubisi]]></dc:creator><pubDate>Wed, 25 Sep 2024 15:16:35 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1727225547568/eff33010-49d4-46d8-90ab-cb87cc2871d2.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Multichain applications are becoming the new norm, but managing governance across these networks remains a significant challenge. For decentralized applications (dApps) with deployments on multiple blockchains, ensuring an easy governance processes while maintaining security, liveness, and resistance to censorship is a complex task. This challenge is particularly evident in projects like <a target="_blank" href="https://uniswap.org/">Uniswap</a>, which has extensively assessed cross-chain platforms to secure its governance across diverse networks. Through this, they discovered <a target="_blank" href="https://www.axelar.network/blog/uniswap-filecoin-bridge-cross-chain-governance">Axelar's robust infrastructure</a> as the key solution.</p>
<p>To address this, developers have long relied on <a target="_blank" href="https://docs.openzeppelin.com/contracts/4.x/governance"><strong>OpenZeppelin Governor</strong></a>, a widely trusted framework for on-chain governance. However, when paired with cross-chain functionality, the complexity increases. This is where <a target="_blank" href="https://github.com/axelarnetwork/interchain-governance-orchestrator"><strong>Axelar's Interchain Governance Orchestrator</strong></a> steps in – a framework for governance actions across multiple chains.</p>
<p>To quickly get started and test the implementation directly, you can find the full code on GitHub <a target="_blank" href="https://github.com/axelarnetwork/interchain-governance-with-openzeppelin-governor-example">here</a>.</p>
<p>In this tutorial, you will learn how to:</p>
<ul>
<li><p>Build and deploy the following EVM smart contracts <code>GovernanceToken</code>, <code>InterchainProposalSender</code>, <code>ThresholdContract</code>, <code>CrossChainGovernor</code>.</p>
</li>
<li><p>Send a governance proposal from a source chain to update a <code>Threshold</code> contract on a destination.</p>
</li>
<li><p>Write test cases to test all the contract's functionality.</p>
</li>
</ul>
<h3 id="heading-prerequisites">Prerequisites</h3>
<ul>
<li><p>A basic understanding of <a target="_blank" href="https://www.tutorialspoint.com/solidity/index.htm">Solidity</a> and <a target="_blank" href="https://www.w3schools.com/js/">JavaScript</a>.</p>
</li>
<li><p>Familiarity with the <a target="_blank" href="https://docs.openzeppelin.com/contracts/4.x/governance">OpenZeppelin Governor contract</a>.</p>
</li>
</ul>
<h2 id="heading-what-is-the-openzeppelin-governor-contract">What is the OpenZeppelin Governor Contract?</h2>
<p>The <a target="_blank" href="https://docs.openzeppelin.com/contracts/4.x/governance">OpenZeppelin Governor contract</a> is an on-chain governance system for decentralized protocols compatible with <a target="_blank" href="https://docs.compound.finance/v2/governance/">Compound's GovernorAlpha and GovernorBravo</a>. It allows governance through token-based voting, where users delegate tokens to gain voting power. Proposals represent executable code changes; only users with sufficient voting power can submit them. Each protocol customizes voting periods and quorum thresholds.</p>
<p>The system includes optional features like <a target="_blank" href="https://docs.openzeppelin.com/contracts/5.x/governance#proposal_lifecycle">proposal delays</a> and <a target="_blank" href="https://docs.openzeppelin.com/contracts/4.x/api/governance#TimelockController">timelocks</a>, providing flexibility in governance processes. Unlike Compound's Governor, the OpenZeppelin Governor can function with or without a timelock.</p>
<h2 id="heading-interchain-governance-orchestrator">Interchain Governance Orchestrator</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1727270247801/04286155-001a-4eac-8600-0e4caa6bcd8e.png" alt="Interchain Governance Orchestrator" class="image--center mx-auto" /></p>
<p><a target="_blank" href="https://github.com/axelarnetwork/interchain-governance-orchestrator/tree/main">Interchain Governance Orchestrator</a> is a system that simplifies cross-chain governance for Web3 applications. It consists of two primary contracts:</p>
<ol>
<li><p><a target="_blank" href="https://github.com/axelarnetwork/interchain-governance-orchestrator/blob/main/contracts/InterchainProposalSender.sol">InterchainProposalSender</a> (on source chain): Encodes and sends proposals to other chains.</p>
</li>
<li><p><a target="_blank" href="https://github.com/axelarnetwork/interchain-governance-orchestrator/blob/main/contracts/InterchainProposalExecutor.sol">InterchainProposalExecutor</a> (on destination chain): Receives and executes proposals on target contracts.</p>
</li>
</ol>
<p>This system allows developers to manage governance across multiple chains more efficiently, reducing complexity and risk.</p>
<h2 id="heading-getting-started-with-axelar-general-message-passing">Getting started with Axelar General Message Passing</h2>
<p><a target="_blank" href="https://docs.axelar.dev/dev/general-message-passing/overview"><strong>Axelar General Message Passing (GMP)</strong></a> empowers developers to call any function on interconnected chains seamlessly.</p>
<p>With GMP, developers gain the ability to:</p>
<ol>
<li><p>Call a contract on chain A and interact with a contract on chain B.</p>
</li>
<li><p>All-in-one gas payment for cross-chain calls</p>
</li>
<li><p>Execute cross-chain transactions by calling a contract on chain A and sending tokens to chain B.</p>
</li>
</ol>
<h2 id="heading-project-setup-and-installation">Project setup and installation</h2>
<h3 id="heading-create-and-initialize-a-project">Create and initialize a project</h3>
<p>Open up your terminal and navigate to any directory of your choice. Run the following commands to create and initiate a project:</p>
<pre><code class="lang-bash">mkdir interchain-governance-with-openzeppelin-governor-example
<span class="hljs-built_in">cd</span> interchain-governance-with-openzeppelin-governor-example

npm init -y
</code></pre>
<h3 id="heading-install-hardhat-and-the-axelarjs-sdk">Install Hardhat and the AxelarJS SDK</h3>
<p>Install <a target="_blank" href="https://hardhat.org/">Hardhat</a>, OpenZeppelin, hardhat toolbox, and the <a target="_blank" href="https://github.com/axelarnetwork/axelarjs-sdk">axelar-gmp-sdk-solidity</a> with the following commands:</p>
<pre><code class="lang-bash">npm install --save-dev hardhat@2.14.0 @openzeppelin/contracts@4.9.0 @axelar-network/axelar-gmp-sdk-solidity@5.10.0 @nomicfoundation/hardhat-toolbox@2.0.2
</code></pre>
<h3 id="heading-initialize-a-hardhat-project">Initialize a Hardhat project</h3>
<pre><code class="lang-bash">npx hardhat init
</code></pre>
<p>Choose "Create a JavaScript project" when prompted.</p>
<pre><code class="lang-bash">888    888                      888 888               888
888    888                      888 888               888
888    888                      888 888               888
8888888888  8888b.  888d888 .d88888 88888b.   8888b.  888888
888    888     <span class="hljs-string">"88b 888P"</span>  d88<span class="hljs-string">" 888 888 "</span>88b     <span class="hljs-string">"88b 888
888    888 .d888888 888    888  888 888  888 .d888888 888
888    888 888  888 888    Y88b 888 888  888 888  888 Y88b.
888    888 "</span>Y888888 888     <span class="hljs-string">"Y88888 888  888 "</span>Y888888  <span class="hljs-string">"Y888

👷 Welcome to Hardhat v2.14.0 👷‍
✔ What do you want to do? · Create a JavaScript project
✔ Hardhat project root: · /interchain-governance-with-openzeppelin-governor-example
✔ Do you want to add a .gitignore? (Y/n) · y
✨ Project created ✨
See the README.md file for some example tasks you can run

Give Hardhat a star on Github if you're enjoying it! ⭐️✨
&lt;https://github.com/NomicFoundation/hardhat&gt;</span>
</code></pre>
<h2 id="heading-build-the-smart-contracts">Build the smart contracts</h2>
<p>In this section, you will build the <code>InterchainCalls</code> library to help define structures for cross-chain calls and contracts <code>GovernanceToken</code>, <code>InterchainProposalSender</code>, <code>ThresholdContract</code>, and <code>CrossChainGovernor</code> for multichain governance.</p>
<h3 id="heading-build-the-interchaincalls-library">Build the <code>InterchainCalls</code> library</h3>
<p>Create a file <code>InterchainCalls.sol</code> in the <code>contracts</code> directory and add the following code snippet to create a library to be reused while implementing the interchain proposal contract and cross-chain governance contract.</p>
<pre><code class="lang-solidity"><span class="hljs-comment">// SPDX-License-Identifier: MIT</span>
<span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> ^0.8.0;</span>

<span class="hljs-comment">/// @title InterchainCalls Library</span>
<span class="hljs-comment">/// @notice This library defines structures for cross-chain calls using Axelar Network</span>
<span class="hljs-class"><span class="hljs-keyword">library</span> <span class="hljs-title">InterchainCalls</span> </span>{

    <span class="hljs-comment">/// @dev Represents a complete interchain call</span>
    <span class="hljs-keyword">struct</span> <span class="hljs-title">InterchainCall</span> {
        <span class="hljs-keyword">string</span> destinationChain; <span class="hljs-comment">// The name of the destination chain</span>
        <span class="hljs-keyword">string</span> destinationContract; <span class="hljs-comment">// The address of the contract on the destination chain</span>
        <span class="hljs-keyword">uint256</span> gas; <span class="hljs-comment">// The amount of gas to be paid for the call</span>
        Call[] calls; <span class="hljs-comment">// An array of calls to be executed on the destination chain</span>
    }

    <span class="hljs-comment">/// @dev Represents a single call to be executed on the destination chain</span>
    <span class="hljs-keyword">struct</span> <span class="hljs-title">Call</span> {
        <span class="hljs-keyword">address</span> target; <span class="hljs-comment">// The address of the contract to call on the destination chain</span>
        <span class="hljs-keyword">uint256</span> value; <span class="hljs-comment">// The amount of native tokens to send with the call</span>
        <span class="hljs-keyword">bytes</span> callData; <span class="hljs-comment">// The encoded function call data</span>
    }
}
</code></pre>
<p>In the code snippet above, you:</p>
<ul>
<li><p>Created an <code>InterchainCalls</code> library with two structs: <code>InterchainCall</code> and <code>Call</code>.</p>
</li>
<li><p><code>InterchainCall</code> defines the overall cross-chain message structure, including destination and multiple calls.</p>
</li>
<li><p><code>Call</code> represents individual function calls on the target chain.</p>
</li>
</ul>
<p>In the next section, you will build the <code>InterchainProposalSender</code>, where you will be utilizing the <code>InterchainCalls</code> library.</p>
<h3 id="heading-build-the-interchain-proposal-sender-contract">Build the Interchain Proposal Sender contract</h3>
<p>Create the <code>InterchainProposalSender</code> contract, a component of your cross-chain governance system. This contract will send proposals from one blockchain to another using the Axelar <a target="_blank" href="https://docs.axelar.dev/dev/general-message-passing/overview/">General Message Passing</a> feature.</p>
<p>The main objectives of this contract are:</p>
<ol>
<li><p>To interface with <a target="_blank" href="https://github.com/axelarnetwork/axelar-cgp-solidity/blob/main/contracts/AxelarGateway.sol/">Axelar's Gateway</a> and <a target="_blank" href="https://docs.axelar.dev/dev/gas-service/intro/">Gas Service</a> for cross-chain communication.</p>
</li>
<li><p>To provide a method for sending proposals to other chains, including the necessary gas payments.</p>
</li>
<li><p>To encode the proposal data in a format that can be understood and executed on the destination chain.</p>
</li>
</ol>
<p>Now, let's create the <code>InterchainProposalSender.sol</code> file in the <code>contracts</code> directory and add the following code snippet to implement the <code>sendProposal</code> function.</p>
<pre><code class="lang-solidity"><span class="hljs-comment">// SPDX-License-Identifier: MIT</span>
<span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> ^0.8.20;</span>

<span class="hljs-keyword">import</span> {<span class="hljs-title">IAxelarGateway</span>} <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IAxelarGateway.sol"</span>;
<span class="hljs-keyword">import</span> {<span class="hljs-title">IAxelarGasService</span>} <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IAxelarGasService.sol"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"./InterchainCalls.sol"</span>;

<span class="hljs-comment">/// @title InterchainProposalSender</span>
<span class="hljs-comment">/// @notice This contract sends cross-chain proposals using the Axelar network</span>
<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">InterchainProposalSender</span> </span>{
    IAxelarGateway <span class="hljs-keyword">public</span> <span class="hljs-keyword">immutable</span> gateway;
    IAxelarGasService <span class="hljs-keyword">public</span> <span class="hljs-keyword">immutable</span> gasService;

    <span class="hljs-function"><span class="hljs-keyword">error</span> <span class="hljs-title">InvalidAddress</span>(<span class="hljs-params"></span>)</span>;
    <span class="hljs-function"><span class="hljs-keyword">error</span> <span class="hljs-title">InvalidFee</span>(<span class="hljs-params"></span>)</span>;

    <span class="hljs-comment">/// @notice Initializes the contract with Axelar Gateway and Gas Service addresses</span>
    <span class="hljs-comment">/// @param _gateway Address of the Axelar Gateway</span>
    <span class="hljs-comment">/// @param _gasService Address of the Axelar Gas Service</span>
    <span class="hljs-function"><span class="hljs-keyword">constructor</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> _gateway, <span class="hljs-keyword">address</span> _gasService</span>) </span>{
        <span class="hljs-keyword">if</span> (_gateway <span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-keyword">address</span>(<span class="hljs-number">0</span>) <span class="hljs-operator">|</span><span class="hljs-operator">|</span> _gasService <span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-keyword">address</span>(<span class="hljs-number">0</span>))
            <span class="hljs-keyword">revert</span> InvalidAddress();
        gateway <span class="hljs-operator">=</span> IAxelarGateway(_gateway);
        gasService <span class="hljs-operator">=</span> IAxelarGasService(_gasService);
    }

    <span class="hljs-comment">/// @notice Sends a proposal to another chain</span>
    <span class="hljs-comment">/// @param destinationChain The name of the destination chain</span>
    <span class="hljs-comment">/// @param destinationContract The address of the contract on the destination chain</span>
    <span class="hljs-comment">/// @param calls An array of calls to be executed on the destination chain</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sendProposal</span>(<span class="hljs-params">
        <span class="hljs-keyword">string</span> <span class="hljs-keyword">memory</span> destinationChain,
        <span class="hljs-keyword">string</span> <span class="hljs-keyword">memory</span> destinationContract,
        InterchainCalls.Call[] <span class="hljs-keyword">calldata</span> calls
    </span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title"><span class="hljs-keyword">payable</span></span> </span>{
        <span class="hljs-built_in">require</span>(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">value</span> <span class="hljs-operator">&gt;</span> <span class="hljs-number">0</span>, <span class="hljs-string">"Gas payment is required"</span>);
        <span class="hljs-keyword">bytes</span> <span class="hljs-keyword">memory</span> payload <span class="hljs-operator">=</span> <span class="hljs-built_in">abi</span>.<span class="hljs-built_in">encode</span>(<span class="hljs-built_in">abi</span>.<span class="hljs-built_in">encodePacked</span>(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>), calls);

        gasService.payNativeGasForContractCall{<span class="hljs-built_in">value</span>: <span class="hljs-built_in">msg</span>.<span class="hljs-built_in">value</span>}(
            <span class="hljs-keyword">address</span>(<span class="hljs-built_in">this</span>),
            destinationChain,
            destinationContract,
            payload,
            <span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>
        );
        gateway().callContract(destinationChain, destinationContract, payload);
    }
}
</code></pre>
<p>In the code snippet above, you:</p>
<ul>
<li><p><strong>Imported</strong> the necessary Axelar interfaces:</p>
<ul>
<li><p><code>IAxelarGateway</code> for cross-chain messaging</p>
</li>
<li><p><code>IAxelarGasService</code> for handling gas payments</p>
</li>
<li><p>Our custom <code>InterchainCalls</code> library for structuring call data</p>
</li>
</ul>
</li>
<li><p><strong>Defined</strong> the <code>InterchainProposalSender</code> contract to send proposals across different blockchain networks via the Axelar network</p>
</li>
<li><p><strong>Initialized</strong> the contract with immutable references to the Axelar Gateway and Gas Service in the constructor, ensuring they are valid addresses:</p>
<ul>
<li>Checked for invalid addresses and reverted with <code>InvalidAddress()</code> if necessary</li>
</ul>
</li>
<li><p><strong>Implemented</strong> the <code>sendProposal</code> function, which:</p>
<ul>
<li><p><strong>Requires</strong> a non-zero <code>msg.value</code> to ensure gas fees are provided (<code>require(msg.value &gt; 0, "Gas payment is required");</code>)</p>
</li>
<li><p><strong>Encodes</strong> the sender's address and the array of calls into a payload using <code>abi.encode</code></p>
</li>
<li><p><strong>Pays</strong> the gas fees for the cross-chain transaction using the Axelar Gas Service</p>
</li>
<li><p><strong>Sends</strong> the proposal to the specified contract on the destination chain via the Axelar Gateway</p>
</li>
</ul>
</li>
</ul>
<h3 id="heading-build-the-governance-token-contract">Build the Governance Token contract</h3>
<p>Voting on a proposal requires voting power, and to allow a user to have this voting power, you need to create the <code>GovernanceToken</code> contract. This token will:</p>
<ol>
<li><p>Provide voting power to token holders.</p>
</li>
<li><p>Implement the ERC20 standard with additional voting and permit capabilities.</p>
</li>
<li><p>Allow the owner to mint new tokens.</p>
</li>
</ol>
<p>This contract combines features from OpenZeppelin's ERC20, ERC20Permit, ERC20Votes, and Ownable contracts to create a governance token suitable for your cross-chain governance system.</p>
<p>Let's implement this contract by creating a new file in our <code>contracts</code> directory and adding the following code snippet.</p>
<pre><code class="lang-solidity"><span class="hljs-comment">// SPDX-License-Identifier: MIT</span>
<span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> ^0.8.20;</span>

<span class="hljs-keyword">import</span> <span class="hljs-string">"@openzeppelin/contracts/token/ERC20/ERC20.sol"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"@openzeppelin/contracts/token/ERC20/extensions/ERC20Votes.sol"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"@openzeppelin/contracts/access/Ownable.sol"</span>;

<span class="hljs-comment">/// @title GovernanceToken</span>
<span class="hljs-comment">/// @notice ERC20 token with voting and permit capabilities for governance</span>
<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">GovernanceToken</span> <span class="hljs-keyword">is</span> <span class="hljs-title">ERC20</span>, <span class="hljs-title">ERC20Permit</span>, <span class="hljs-title">ERC20Votes</span>, <span class="hljs-title">Ownable</span> </span>{
    <span class="hljs-keyword">uint256</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">constant</span> MAX_SUPPLY <span class="hljs-operator">=</span> <span class="hljs-number">1000000</span> <span class="hljs-operator">*</span> <span class="hljs-number">10</span> <span class="hljs-operator">*</span><span class="hljs-operator">*</span> <span class="hljs-number">18</span>; <span class="hljs-comment">// 1 million tokens</span>

    <span class="hljs-comment">/// @notice Initializes the token and mints the entire supply to the initial owner</span>
    <span class="hljs-comment">/// @param initialOwner Address of the initial token owner</span>
    <span class="hljs-function"><span class="hljs-keyword">constructor</span>(<span class="hljs-params">
        <span class="hljs-keyword">address</span> initialOwner
    </span>)
        <span class="hljs-title">ERC20</span>(<span class="hljs-params"><span class="hljs-string">"GovernanceToken"</span>, <span class="hljs-string">"MGT"</span></span>)
        <span class="hljs-title">ERC20Permit</span>(<span class="hljs-params"><span class="hljs-string">"GovernanceToken"</span></span>)
        <span class="hljs-title">Ownable</span>(<span class="hljs-params">initialOwner</span>)
    </span>{
        _mint(initialOwner, MAX_SUPPLY);
    }

    <span class="hljs-comment">/// @notice Mints new tokens (only callable by owner)</span>
    <span class="hljs-comment">/// @param to Address to receive the minted tokens</span>
    <span class="hljs-comment">/// @param amount Amount of tokens to mint</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">mint</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> to, <span class="hljs-keyword">uint256</span> amount</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title">onlyOwner</span> </span>{
        _mint(to, amount);
    }

    <span class="hljs-comment">// The following functions are overrides required by Solidity</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">_update</span>(<span class="hljs-params">
        <span class="hljs-keyword">address</span> <span class="hljs-keyword">from</span>,
        <span class="hljs-keyword">address</span> to,
        <span class="hljs-keyword">uint256</span> amount
    </span>) <span class="hljs-title"><span class="hljs-keyword">internal</span></span> <span class="hljs-title"><span class="hljs-keyword">override</span></span>(<span class="hljs-params">ERC20, ERC20Votes</span>) </span>{
        <span class="hljs-built_in">super</span>._update(<span class="hljs-keyword">from</span>, to, amount);
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">nonces</span>(<span class="hljs-params">
        <span class="hljs-keyword">address</span> owner
    </span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">view</span></span> <span class="hljs-title"><span class="hljs-keyword">override</span></span>(<span class="hljs-params">ERC20Permit, Nonces</span>) <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">uint256</span></span>) </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-built_in">super</span>.nonces(owner);
    }
}
</code></pre>
<p>In the code snippet above, you:</p>
<ul>
<li><p>Set a maximum supply of 1 million tokens</p>
</li>
<li><p>Implemented a constructor that mints the entire supply to the initial owner</p>
</li>
<li><p>Added a <code>mint</code> function that allows the owner to create new tokens</p>
</li>
<li><p>Overrode the <code>_update</code> function to ensure proper functionality with ERC20Votes</p>
</li>
<li><p>Overrode the <code>nonces</code> function to resolve conflicts between ERC20Permit and Nonces</p>
</li>
</ul>
<h3 id="heading-build-the-threshold-contract-contract">Build the Threshold Contract contract</h3>
<p>Now, you'll create the <code>ThresholdContract</code>, which will be the target of your cross-chain governance proposals. This contract will:</p>
<ol>
<li><p>Store a threshold value that can be updated through governance.</p>
</li>
<li><p>Provide a function to update the threshold.</p>
</li>
<li><p>Emit an event when the threshold is changed.</p>
</li>
</ol>
<p>This simple contract will serve as an example of how cross-chain governance can be used to manage parameters on different blockchains.</p>
<p>Let's implement this contract in our <code>contracts</code> directory. Create a file <code>ThresholdContract.sol</code> inside the <code>contracts</code> directory, then add the following code snippet.</p>
<pre><code class="lang-solidity"><span class="hljs-comment">// SPDX-License-Identifier: MIT</span>
<span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> ^0.8.0;</span>

<span class="hljs-comment">/// @title ThresholdContract</span>
<span class="hljs-comment">/// @notice A simple contract to manage and update a threshold value</span>
<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">ThresholdContract</span> </span>{
    <span class="hljs-keyword">uint256</span> <span class="hljs-keyword">public</span> threshold;

    <span class="hljs-function"><span class="hljs-keyword">event</span> <span class="hljs-title">ThresholdUpdated</span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span> newThreshold</span>)</span>;

    <span class="hljs-comment">/// @notice Updates the threshold to a new value</span>
    <span class="hljs-comment">/// @param newThreshold The new threshold value to set</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">updateThreshold</span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span> newThreshold</span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> </span>{
        threshold <span class="hljs-operator">=</span> newThreshold;
        <span class="hljs-keyword">emit</span> ThresholdUpdated(newThreshold);
    }
}
</code></pre>
<h3 id="heading-build-the-crosschain-governor-contract">Build the CrossChain Governor contract</h3>
<p>The <code>CrossChainGovernor</code> contract is the most important part of this tutorial. It combines standard on-chain governance with cross-chain capabilities. This contract will allow token holders to propose and vote on actions that can be executed across different blockchain networks.</p>
<h4 id="heading-contract-declaration-and-imports">Contract declaration and imports</h4>
<p>Before adding the code, you want to set up the basic structure of your <code>CrossChainGovernor</code> contract. This includes importing necessary OpenZeppelin and Axelar contracts, as well as your custom <code>InterchainCalls</code> and <code>InterchainProposalSender</code> contracts. You'll also declare your contract and its inheritance.</p>
<pre><code class="lang-solidity"><span class="hljs-comment">// SPDX-License-Identifier: MIT</span>
<span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> ^0.8.20;</span>

<span class="hljs-comment">// Import necessary OpenZeppelin and Axelar contracts</span>
<span class="hljs-keyword">import</span> <span class="hljs-string">"@openzeppelin/contracts/governance/Governor.sol"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"@openzeppelin/contracts/governance/extensions/GovernorCountingSimple.sol"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"@openzeppelin/contracts/governance/extensions/GovernorVotes.sol"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"@axelar-network/axelar-gmp-sdk-solidity/contracts/executable/AxelarExecutable.sol"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IAxelarGasService.sol"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"./InterchainCalls.sol"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"./InterchainProposalSender.sol"</span>;

<span class="hljs-comment">/**
 * @title CrossChainGovernor
 * @dev A governance contract that enables cross-chain proposal creation and execution using Axelar Network.
 * @notice This contract allows for creating and executing threshold update proposals across different blockchain networks.
 */</span>
<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">CrossChainGovernor</span> <span class="hljs-keyword">is</span>
    <span class="hljs-title">Governor</span>,
    <span class="hljs-title">GovernorCountingSimple</span>,
    <span class="hljs-title">GovernorVotes</span>,
    <span class="hljs-title">AxelarExecutable</span>
</span>{
    <span class="hljs-comment">// Contract body will be added in subsequent steps</span>
}
</code></pre>
<h4 id="heading-state-variables-and-events">State variables and events</h4>
<p>Add the state variables and events for your contract. This includes variables for the Axelar gas service, proposal sender, threshold address, and mappings for whitelisted callers and senders. You'll also define the <code>CrossChainProposal</code> struct and relevant events.</p>
<pre><code class="lang-solidity"><span class="hljs-comment">//...</span>

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">CrossChainGovernor</span> <span class="hljs-keyword">is</span> <span class="hljs-title">Governor</span>, <span class="hljs-title">GovernorSettings</span>, <span class="hljs-title">GovernorCountingSimple</span>, <span class="hljs-title">GovernorVotes</span>, <span class="hljs-title">AxelarExecutable</span> </span>{
    <span class="hljs-comment">//...</span>

    <span class="hljs-comment">// Axelar gas service for cross-chain transactions</span>
    IAxelarGasService <span class="hljs-keyword">public</span> <span class="hljs-keyword">immutable</span> gasService;

    <span class="hljs-comment">// Contract for sending interchain proposals</span>
    InterchainProposalSender <span class="hljs-keyword">public</span> <span class="hljs-keyword">immutable</span> proposalSender;

    <span class="hljs-comment">// Mappings to store whitelisted senders and callers for cross-chain governance</span>
    <span class="hljs-keyword">mapping</span>(<span class="hljs-keyword">string</span> <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> <span class="hljs-keyword">mapping</span>(<span class="hljs-keyword">string</span> <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> <span class="hljs-keyword">bool</span>)) <span class="hljs-keyword">public</span> whitelistedSenders;
    <span class="hljs-keyword">mapping</span>(<span class="hljs-keyword">string</span> <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> <span class="hljs-keyword">mapping</span>(<span class="hljs-keyword">bytes</span> <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> <span class="hljs-keyword">bool</span>)) <span class="hljs-keyword">public</span> whitelistedCallers;

    <span class="hljs-comment">// Structure to store threshold proposal details</span>
    <span class="hljs-keyword">struct</span> <span class="hljs-title">ThresholdProposal</span> {
        <span class="hljs-keyword">string</span> destinationChain;
        <span class="hljs-keyword">string</span> destinationContract;
        <span class="hljs-keyword">address</span> thresholdContract;
        <span class="hljs-keyword">uint256</span> newThreshold;
    }

    <span class="hljs-comment">// Mapping to store threshold proposals</span>
    <span class="hljs-keyword">mapping</span>(<span class="hljs-keyword">uint256</span> <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> ThresholdProposal) <span class="hljs-keyword">public</span> thresholdProposals;

    <span class="hljs-comment">/**
     * @dev Emitted when a threshold proposal is created.
     * @param proposalId The ID of the created proposal.
     * @param destinationChain The target blockchain for the proposal.
     * @param destinationContract The address of the contract on the destination chain.
     * @param thresholdContract The address of the threshold contract.
     * @param newThreshold The proposed new threshold value.
     */</span>
    <span class="hljs-function"><span class="hljs-keyword">event</span> <span class="hljs-title">ThresholdProposalCreated</span>(<span class="hljs-params">
        <span class="hljs-keyword">uint256</span> proposalId,
        <span class="hljs-keyword">string</span> destinationChain,
        <span class="hljs-keyword">string</span> destinationContract,
        <span class="hljs-keyword">address</span> thresholdContract,
        <span class="hljs-keyword">uint256</span> newThreshold
    </span>)</span>;

    <span class="hljs-comment">/**
     * @dev Emitted when a whitelisted caller is set.
     * @param sourceChain The source blockchain of the caller.
     * @param sourceCaller The address of the caller.
     * @param whitelisted The whitelist status of the caller.
     */</span>
    <span class="hljs-function"><span class="hljs-keyword">event</span> <span class="hljs-title">WhitelistedCallerSet</span>(<span class="hljs-params">
        <span class="hljs-keyword">string</span> sourceChain,
        <span class="hljs-keyword">bytes</span> sourceCaller,
        <span class="hljs-keyword">bool</span> whitelisted
    </span>)</span>;

    <span class="hljs-comment">/**
     * @dev Emitted when a cross-chain proposal is executed.
     * @param proposalHash The unique hash of the executed proposal.
     */</span>
    <span class="hljs-function"><span class="hljs-keyword">event</span> <span class="hljs-title">CrossChainProposalExecuted</span>(<span class="hljs-params"><span class="hljs-keyword">bytes32</span> <span class="hljs-keyword">indexed</span> proposalHash</span>)</span>;

    <span class="hljs-comment">/**
     * @dev Emitted when a threshold proposal is executed.
     * @param proposalId The ID of the executed proposal.
     */</span>
    <span class="hljs-function"><span class="hljs-keyword">event</span> <span class="hljs-title">ThresholdProposalExecuted</span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span> <span class="hljs-keyword">indexed</span> proposalId</span>)</span>;

    <span class="hljs-comment">/**
     * @dev Emitted when a whitelisted sender is set.
     * @param sourceChain The source blockchain of the sender.
     * @param sourceSender The address of the sender.
     * @param whitelisted The whitelist status of the sender.
     */</span>
    <span class="hljs-function"><span class="hljs-keyword">event</span> <span class="hljs-title">WhitelistedSenderSet</span>(<span class="hljs-params">
        <span class="hljs-keyword">string</span> sourceChain,
        <span class="hljs-keyword">string</span> sourceSender,
        <span class="hljs-keyword">bool</span> whitelisted
    </span>)</span>;

    <span class="hljs-comment">// Constructor here</span>
}
</code></pre>
<h4 id="heading-add-a-constructor">Add a constructor</h4>
<p>Add the constructor for your <code>CrossChainGovernor</code> contract. This will initialize the contract with the necessary parameters, including the governance token, Axelar gateway, gas service, proposal sender, and threshold address.</p>
<pre><code class="lang-solidity"><span class="hljs-comment">//...</span>

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">CrossChainGovernor</span> <span class="hljs-keyword">is</span> <span class="hljs-title">Governor</span>, <span class="hljs-title">GovernorSettings</span>, <span class="hljs-title">GovernorCountingSimple</span>, <span class="hljs-title">GovernorVotes</span>, <span class="hljs-title">AxelarExecutable</span> </span>{
    <span class="hljs-comment">//...</span>

    <span class="hljs-comment">/**
     * @dev Constructor to initialize the CrossChainGovernor contract.
     * @param _name The name of the governor.
     * @param _token The voting token address.
     * @param _gateway The Axelar gateway address.
     * @param _gasService The Axelar gas service address.
     * @param _proposalSender The address of the InterchainProposalSender contract.
     */</span>
    <span class="hljs-function"><span class="hljs-keyword">constructor</span>(<span class="hljs-params">
        <span class="hljs-keyword">string</span> <span class="hljs-keyword">memory</span> _name,
        IVotes _token,
        <span class="hljs-keyword">address</span> _gateway,
        <span class="hljs-keyword">address</span> _gasService,
        <span class="hljs-keyword">address</span> _proposalSender
    </span>) <span class="hljs-title">Governor</span>(<span class="hljs-params">_name</span>) <span class="hljs-title">GovernorVotes</span>(<span class="hljs-params">_token</span>) <span class="hljs-title">AxelarExecutable</span>(<span class="hljs-params">_gateway</span>) </span>{
        gasService <span class="hljs-operator">=</span> IAxelarGasService(_gasService);
        proposalSender <span class="hljs-operator">=</span> InterchainProposalSender(_proposalSender);
    }

 }
</code></pre>
<h4 id="heading-add-whitelisting-and-proposal-threshold-update">Add whitelisting and proposal threshold update</h4>
<p>In this step, you will add whitelisting and proposal threshold functions. These functions will be used on the source chain to whitelist and propose updating thresholds on the destination chain.</p>
<pre><code class="lang-solidity"><span class="hljs-comment">//...</span>

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">CrossChainGovernor</span> <span class="hljs-keyword">is</span> <span class="hljs-title">Governor</span>, <span class="hljs-title">GovernorSettings</span>, <span class="hljs-title">GovernorCountingSimple</span>, <span class="hljs-title">GovernorVotes</span>, <span class="hljs-title">AxelarExecutable</span> </span>{
    <span class="hljs-comment">//...</span>

    <span class="hljs-comment">/**
     * @dev Sets a whitelisted proposal sender.
     * @param sourceChain The source blockchain of the sender.
     * @param sourceSender The address of the sender to be whitelisted.
     * @param whitelisted The whitelist status to be set.
     */</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">setWhitelistedProposalSender</span>(<span class="hljs-params">
        <span class="hljs-keyword">string</span> <span class="hljs-keyword">calldata</span> sourceChain,
        <span class="hljs-keyword">string</span> <span class="hljs-keyword">calldata</span> sourceSender,
        <span class="hljs-keyword">bool</span> whitelisted
    </span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title">onlyGovernance</span> </span>{
        whitelistedSenders[sourceChain][sourceSender] <span class="hljs-operator">=</span> whitelisted;
        <span class="hljs-keyword">emit</span> WhitelistedSenderSet(sourceChain, sourceSender, whitelisted);
    }

    <span class="hljs-comment">/**
     * @dev Sets a whitelisted proposal caller.
     * @param sourceChain The source blockchain of the caller.
     * @param sourceCaller The address of the caller to be whitelisted.
     * @param whitelisted The whitelist status to be set.
     */</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">setWhitelistedProposalCaller</span>(<span class="hljs-params">
        <span class="hljs-keyword">string</span> <span class="hljs-keyword">calldata</span> sourceChain,
        <span class="hljs-keyword">bytes</span> <span class="hljs-keyword">memory</span> sourceCaller,
        <span class="hljs-keyword">bool</span> whitelisted
    </span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title">onlyGovernance</span> </span>{
        whitelistedCallers[sourceChain][sourceCaller] <span class="hljs-operator">=</span> whitelisted;
        <span class="hljs-keyword">emit</span> WhitelistedCallerSet(sourceChain, sourceCaller, whitelisted);
    }

    <span class="hljs-comment">/**
     * @dev Proposes a threshold update.
     * @param destinationChain The target blockchain for the proposal.
     * @param destinationContract The address of the contract on the destination chain.
     * @param thresholdContract The address of the threshold contract.
     * @param newThreshold The proposed new threshold value.
     * @return proposalId The ID of the created proposal.
     */</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">proposeThresholdUpdate</span>(<span class="hljs-params">
        <span class="hljs-keyword">string</span> <span class="hljs-keyword">memory</span> destinationChain,
        <span class="hljs-keyword">string</span> <span class="hljs-keyword">memory</span> destinationContract,
        <span class="hljs-keyword">address</span> thresholdContract,
        <span class="hljs-keyword">uint256</span> newThreshold
    </span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">uint256</span> proposalId</span>) </span>{
        <span class="hljs-comment">// Create proposal parameters</span>
        <span class="hljs-keyword">address</span>[] <span class="hljs-keyword">memory</span> targets <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-keyword">address</span>[](<span class="hljs-number">1</span>);
        <span class="hljs-keyword">uint256</span>[] <span class="hljs-keyword">memory</span> values <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-keyword">uint256</span>[](<span class="hljs-number">1</span>);
        <span class="hljs-keyword">bytes</span>[] <span class="hljs-keyword">memory</span> calldatas <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-keyword">bytes</span>[](<span class="hljs-number">1</span>);

        targets[<span class="hljs-number">0</span>] <span class="hljs-operator">=</span> thresholdContract;
        values[<span class="hljs-number">0</span>] <span class="hljs-operator">=</span> <span class="hljs-number">0</span>;
        calldatas[<span class="hljs-number">0</span>] <span class="hljs-operator">=</span> <span class="hljs-built_in">abi</span>.<span class="hljs-built_in">encodeWithSignature</span>(
            <span class="hljs-string">"updateThreshold(uint256)"</span>,
            newThreshold
        );

        <span class="hljs-comment">// Create the proposal</span>
        proposalId <span class="hljs-operator">=</span> propose(
            targets,
            values,
            calldatas,
            <span class="hljs-string">"Proposal to update the threshold contract"</span>
        );

        <span class="hljs-comment">// Store the threshold proposal details</span>
        thresholdProposals[proposalId] <span class="hljs-operator">=</span> ThresholdProposal({
            destinationChain: destinationChain,
            destinationContract: destinationContract,
            thresholdContract: thresholdContract,
            newThreshold: newThreshold
        });

        <span class="hljs-comment">// Emit event for threshold proposal creation</span>
        <span class="hljs-keyword">emit</span> ThresholdProposalCreated(
            proposalId,
            destinationChain,
            destinationContract,
            thresholdContract,
            newThreshold
        );

        <span class="hljs-keyword">return</span> proposalId;
    }
 }
</code></pre>
<h4 id="heading-add-execute-threshold-proposal-function">Add execute threshold proposal function</h4>
<p>Next, add a function to execute threshold proposals using the proposal ID and other helper functions like <code>_getProposalTargets</code>, <code>_getProposalValues</code>, and <code>_getProposalCalldatas</code>.</p>
<pre><code class="lang-solidity"><span class="hljs-comment">//...</span>

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">CrossChainGovernor</span> <span class="hljs-keyword">is</span> <span class="hljs-title">Governor</span>, <span class="hljs-title">GovernorSettings</span>, <span class="hljs-title">GovernorCountingSimple</span>, <span class="hljs-title">GovernorVotes</span>, <span class="hljs-title">AxelarExecutable</span> </span>{
    <span class="hljs-comment">//...</span>

      <span class="hljs-comment">/**
     * @dev Executes a threshold proposal.
     * @param proposalId The ID of the proposal to be executed.
     */</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">executeThresholdProposal</span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span> proposalId</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">payable</span></span> </span>{
        <span class="hljs-built_in">require</span>(
            state(proposalId) <span class="hljs-operator">=</span><span class="hljs-operator">=</span> ProposalState.Succeeded,
            <span class="hljs-string">"Proposal must be succeeded"</span>
        );
        ThresholdProposal <span class="hljs-keyword">memory</span> proposal <span class="hljs-operator">=</span> thresholdProposals[proposalId];
        InterchainCalls.Call[] <span class="hljs-keyword">memory</span> calls <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> InterchainCalls.Call[](<span class="hljs-number">1</span>);
        calls[<span class="hljs-number">0</span>] <span class="hljs-operator">=</span> InterchainCalls.Call({
            target: proposal.thresholdContract,
            <span class="hljs-built_in">value</span>: <span class="hljs-number">0</span>,
            callData: <span class="hljs-built_in">abi</span>.<span class="hljs-built_in">encodeWithSignature</span>(
                <span class="hljs-string">"updateThreshold(uint256)"</span>,
                proposal.newThreshold
            )
        });

        <span class="hljs-comment">// Send the proposal to the destination chain</span>
        proposalSender.sendProposal{<span class="hljs-built_in">value</span>: <span class="hljs-built_in">msg</span>.<span class="hljs-built_in">value</span>}(
            proposal.destinationChain,
            proposal.destinationContract,
            calls
        );

        <span class="hljs-comment">// Execute the proposal on the current chain</span>
        <span class="hljs-built_in">super</span>.execute(
            _getProposalTargets(proposalId),
            _getProposalValues(),
            _getProposalCalldatas(proposalId),
            <span class="hljs-built_in">keccak256</span>(<span class="hljs-keyword">bytes</span>(<span class="hljs-string">"Proposal to update the threshold contract"</span>))
        );

        <span class="hljs-comment">// Emit event for threshold proposal execution</span>
        <span class="hljs-keyword">emit</span> ThresholdProposalExecuted(proposalId);
    }

    <span class="hljs-comment">/**
     * @dev Internal function to get proposal targets.
     * @param proposalId The ID of the proposal.
     * @return An array of target addresses for the proposal.
     */</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">_getProposalTargets</span>(<span class="hljs-params">
        <span class="hljs-keyword">uint256</span> proposalId
    </span>) <span class="hljs-title"><span class="hljs-keyword">internal</span></span> <span class="hljs-title"><span class="hljs-keyword">view</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">address</span>[] <span class="hljs-keyword">memory</span></span>) </span>{
        <span class="hljs-keyword">address</span>[] <span class="hljs-keyword">memory</span> targets <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-keyword">address</span>[](<span class="hljs-number">1</span>);
        targets[<span class="hljs-number">0</span>] <span class="hljs-operator">=</span> thresholdProposals[proposalId].thresholdContract;
        <span class="hljs-keyword">return</span> targets;
    }

    <span class="hljs-comment">/**
     * @dev Internal function to get proposal values.
     * @return An array of values for the proposal (always 0 in this case).
     */</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">_getProposalValues</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">internal</span></span> <span class="hljs-title"><span class="hljs-keyword">pure</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">uint256</span>[] <span class="hljs-keyword">memory</span></span>) </span>{
        <span class="hljs-keyword">uint256</span>[] <span class="hljs-keyword">memory</span> values <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-keyword">uint256</span>[](<span class="hljs-number">1</span>);
        values[<span class="hljs-number">0</span>] <span class="hljs-operator">=</span> <span class="hljs-number">0</span>;
        <span class="hljs-keyword">return</span> values;
    }

    <span class="hljs-comment">/**
     * @dev Internal function to get proposal calldatas.
     * @param proposalId The ID of the proposal.
     * @return An array of calldata for the proposal.
     */</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">_getProposalCalldatas</span>(<span class="hljs-params">
        <span class="hljs-keyword">uint256</span> proposalId
    </span>) <span class="hljs-title"><span class="hljs-keyword">internal</span></span> <span class="hljs-title"><span class="hljs-keyword">view</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">bytes</span>[] <span class="hljs-keyword">memory</span></span>) </span>{
        <span class="hljs-keyword">bytes</span>[] <span class="hljs-keyword">memory</span> calldatas <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-keyword">bytes</span>[](<span class="hljs-number">1</span>);
        calldatas[<span class="hljs-number">0</span>] <span class="hljs-operator">=</span> <span class="hljs-built_in">abi</span>.<span class="hljs-built_in">encodeWithSignature</span>(
            <span class="hljs-string">"updateThreshold(uint256)"</span>,
            thresholdProposals[proposalId].newThreshold
        );
        <span class="hljs-keyword">return</span> calldatas;
    }

}
</code></pre>
<h4 id="heading-add-execute-function">Add <code>_execute</code> function</h4>
<p>To execute a cross-chain call received from another chain, you need to implement the <code>_execute</code> function that receives and processes cross-chain calls on the destination chain.</p>
<pre><code class="lang-solidity"><span class="hljs-comment">//...</span>

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">CrossChainGovernor</span> <span class="hljs-keyword">is</span> <span class="hljs-title">Governor</span>, <span class="hljs-title">GovernorSettings</span>, <span class="hljs-title">GovernorCountingSimple</span>, <span class="hljs-title">GovernorVotes</span>, <span class="hljs-title">AxelarExecutable</span> </span>{

    <span class="hljs-comment">//...</span>

    <span class="hljs-comment">/// @notice Executes a cross-chain call received from another chain</span>
    <span class="hljs-comment">/// @param sourceChain The name of the source chain</span>
    <span class="hljs-comment">/// @param sourceAddress The address of the sender on the source chain</span>
    <span class="hljs-comment">/// @param payload The encoded payload containing the calls to be executed</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">_execute</span>(<span class="hljs-params">
        <span class="hljs-keyword">bytes32</span> commandId,
        <span class="hljs-keyword">string</span> <span class="hljs-keyword">calldata</span> sourceChain,
        <span class="hljs-keyword">string</span> <span class="hljs-keyword">calldata</span> sourceAddress,
        <span class="hljs-keyword">bytes</span> <span class="hljs-keyword">calldata</span> payload
    </span>) <span class="hljs-title"><span class="hljs-keyword">internal</span></span> <span class="hljs-title"><span class="hljs-keyword">override</span></span> </span>{
        <span class="hljs-keyword">if</span> (<span class="hljs-operator">!</span>whitelistedSenders[sourceChain][sourceAddress]) {
            <span class="hljs-keyword">revert</span> NotWhitelistedSourceAddress();
        }

        (<span class="hljs-keyword">bytes</span> <span class="hljs-keyword">memory</span> sourceCaller, InterchainCalls.Call[] <span class="hljs-keyword">memory</span> calls) <span class="hljs-operator">=</span> <span class="hljs-built_in">abi</span>
            .decode(payload, (<span class="hljs-keyword">bytes</span>, InterchainCalls.Call[]));

        <span class="hljs-keyword">if</span> (<span class="hljs-operator">!</span>whitelistedCallers[sourceChain][sourceCaller]) {
            <span class="hljs-keyword">revert</span> NotWhitelistedCaller();
        }

        _executeProposal(calls);

        <span class="hljs-keyword">emit</span> CrossChainProposalExecuted(sourceChain, sourceAddress, payload);
    }

    <span class="hljs-comment">/// @notice Executes the calls in a cross-chain proposal</span>
    <span class="hljs-comment">/// @param calls An array of calls to be executed</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">_executeProposal</span>(<span class="hljs-params">InterchainCalls.Call[] <span class="hljs-keyword">memory</span> calls</span>) <span class="hljs-title"><span class="hljs-keyword">internal</span></span> </span>{
        <span class="hljs-keyword">uint256</span> length <span class="hljs-operator">=</span> calls.<span class="hljs-built_in">length</span>;

        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">uint256</span> i <span class="hljs-operator">=</span> <span class="hljs-number">0</span>; i <span class="hljs-operator">&lt;</span> length; i<span class="hljs-operator">+</span><span class="hljs-operator">+</span>) {
            InterchainCalls.Call <span class="hljs-keyword">memory</span> call <span class="hljs-operator">=</span> calls[i];
            (<span class="hljs-keyword">bool</span> success, <span class="hljs-keyword">bytes</span> <span class="hljs-keyword">memory</span> result) <span class="hljs-operator">=</span> call.target.<span class="hljs-built_in">call</span>{
                <span class="hljs-built_in">value</span>: call.<span class="hljs-built_in">value</span>
            }(call.callData);

            <span class="hljs-keyword">if</span> (<span class="hljs-operator">!</span>success) {
                _onTargetExecutionFailed(call, result);
            }
        }
    }

    <span class="hljs-comment">/// @notice Handles the failure of a call execution</span>
    <span class="hljs-comment">/// @param call The call that failed</span>
    <span class="hljs-comment">/// @param result The result of the failed call</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">_onTargetExecutionFailed</span>(<span class="hljs-params">
        InterchainCalls.Call <span class="hljs-keyword">memory</span> call,
        <span class="hljs-keyword">bytes</span> <span class="hljs-keyword">memory</span> result
    </span>) <span class="hljs-title"><span class="hljs-keyword">internal</span></span> <span class="hljs-title"><span class="hljs-keyword">pure</span></span> </span>{
        <span class="hljs-keyword">if</span> (result.<span class="hljs-built_in">length</span> <span class="hljs-operator">&gt;</span> <span class="hljs-number">0</span>) {
            <span class="hljs-keyword">assembly</span> {
                <span class="hljs-keyword">revert</span>(<span class="hljs-built_in">add</span>(<span class="hljs-number">32</span>, result), <span class="hljs-built_in">mload</span>(result))
            }
        } <span class="hljs-keyword">else</span> {
            <span class="hljs-keyword">revert</span> ProposalExecuteFailed();
        }
    }
 }
</code></pre>
<h4 id="heading-openzeppelin-governor-functions">OpenZeppelin Governor Functions</h4>
<p>Finally, add the required overrides for OpenZeppelin Governor functions. These include <code>votingDelay</code>, <code>votingPeriod</code>, and <code>quorum</code>.</p>
<pre><code class="lang-solidity"><span class="hljs-comment">//...</span>

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">CrossChainGovernor</span> <span class="hljs-keyword">is</span> <span class="hljs-title">Governor</span>, <span class="hljs-title">GovernorSettings</span>, <span class="hljs-title">GovernorCountingSimple</span>, <span class="hljs-title">GovernorVotes</span>, <span class="hljs-title">AxelarExecutable</span> </span>{

    <span class="hljs-comment">//...</span>

     <span class="hljs-comment">/**
     * @dev Returns the voting delay.
     * @return The number of blocks between proposal creation and voting start.
     */</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">votingDelay</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">pure</span></span> <span class="hljs-title"><span class="hljs-keyword">override</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">uint256</span></span>) </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-number">1</span>;
    }

    <span class="hljs-comment">/**
     * @dev Returns the voting period.
     * @return The number of blocks for the voting period.
     */</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">votingPeriod</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">pure</span></span> <span class="hljs-title"><span class="hljs-keyword">override</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">uint256</span></span>) </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-number">50400</span>;
    }

    <span class="hljs-comment">/**
     * @dev Returns the quorum required for a proposal to pass.
     * @return The minimum number of votes required for a quorum.
     */</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">quorum</span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span></span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">pure</span></span> <span class="hljs-title"><span class="hljs-keyword">override</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">uint256</span></span>) </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-number">1e18</span>;
    }
}
</code></pre>
<h2 id="heading-test-the-contracts">Test the contracts</h2>
<p>You have successfully implemented all the contracts required to establish cross-chain governance with the OpenZeppelin governor. Now, you need to write a unit test to ensure that all the functions implemented in your contracts work correctly.</p>
<p>You will create test cases for each prominent system feature, verifying deployment, governance settings, whitelisting, proposal lifecycle, voting, and execution. Follow along as we walk through each test case.</p>
<h3 id="heading-create-mockaxelargateway-and-mockaxelargasservice-files">Create MockAxelarGateway and MockAxelarGasService files</h3>
<p>Before proceeding to test the <code>CrossChainGovernor</code> contract, you need to create mock contracts for <code>AxelarGateway</code> and <code>AxelarGasService</code>. These mock contracts simulate the behavior of the real Axelar contracts and will allow you to run the tests effectively.</p>
<p>You should place these mock contracts in a folder called <code>mock</code> inside the <code>contracts</code> directory.</p>
<h4 id="heading-create-mockaxelargatewaysol">Create <code>MockAxelarGateway.sol</code></h4>
<p>Navigate to the <code>contracts/mock</code> directory and create a file named <code>MockAxelarGateway.sol</code>. Add the following code to mock the basic functionality of Axelar's gateway.</p>
<pre><code class="lang-solidity"><span class="hljs-comment">// SPDX-License-Identifier: MIT</span>
<span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> ^0.8.0;</span>

<span class="hljs-comment">/// @title MockAxelarGateway</span>
<span class="hljs-comment">/// @dev This is a mock contract for testing purposes that simulates the behavior of AxelarGateway.</span>
<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">MockAxelarGateway</span> </span>{
    <span class="hljs-comment">/// @notice Simulates the cross-chain contract call</span>
    <span class="hljs-comment">/// @param destinationChain The chain the contract call is destined for</span>
    <span class="hljs-comment">/// @param destinationContract The contract address on the destination chain</span>
    <span class="hljs-comment">/// @param payload The data payload sent to the destination contract</span>
        <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">callContract</span>(<span class="hljs-params">
        <span class="hljs-keyword">string</span> <span class="hljs-keyword">memory</span>,
        <span class="hljs-keyword">string</span> <span class="hljs-keyword">memory</span>,
        <span class="hljs-keyword">bytes</span> <span class="hljs-keyword">memory</span>
    </span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title"><span class="hljs-keyword">pure</span></span> </span>{}
}
</code></pre>
<h4 id="heading-create-mockaxelargasservicesol">Create <code>MockAxelarGasService.sol</code></h4>
<p>Similarly, create another file in the same folder named <code>MockAxelarGasService.sol</code> and add the following code to simulate the Axelar gas service.</p>
<pre><code class="lang-solidity"><span class="hljs-comment">// SPDX-License-Identifier: MIT</span>
<span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> ^0.8.0;</span>

<span class="hljs-comment">/// @title MockAxelarGasService</span>
<span class="hljs-comment">/// @dev This is a mock contract for testing purposes that simulates the behavior of AxelarGasService.</span>
<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">MockAxelarGasService</span> </span>{
    <span class="hljs-comment">/// @notice Simulates the payment of gas fees for cross-chain calls</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">payNativeGasForContractCall</span>(<span class="hljs-params">
        <span class="hljs-keyword">address</span>,
        <span class="hljs-keyword">string</span> <span class="hljs-keyword">memory</span>,
        <span class="hljs-keyword">string</span> <span class="hljs-keyword">memory</span>,
        <span class="hljs-keyword">bytes</span> <span class="hljs-keyword">memory</span>,
        <span class="hljs-keyword">address</span>
    </span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title"><span class="hljs-keyword">payable</span></span> </span>{}
}
</code></pre>
<p>Your folder structure should now look like this:</p>
<pre><code class="lang-bash">/contracts
   └── /mock
         ├── MockAxelarGateway.sol
         └── MockAxelarGasService.sol
</code></pre>
<h3 id="heading-create-the-crosschaingovernortestjs-file">Create the <code>CrossChainGovernor.test.js</code> file</h3>
<p>Inside the <code>test</code> folder, create a file named <code>CrossChainGovernor.test.js</code>. This file will contain all your unit tests for the <code>CrossChainGovernor</code> contract.</p>
<h3 id="heading-import-dependencies">Import dependencies</h3>
<p>Start by importing the necessary modules and tools. In your <code>CrossChainGovernor.test.js</code> file, add the following code:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> { ethers } = <span class="hljs-built_in">require</span>(<span class="hljs-string">"hardhat"</span>);
<span class="hljs-keyword">const</span> { expect } = <span class="hljs-built_in">require</span>(<span class="hljs-string">"chai"</span>);
<span class="hljs-keyword">const</span> { anyValue } = <span class="hljs-built_in">require</span>(<span class="hljs-string">"@nomicfoundation/hardhat-chai-matchers/withArgs"</span>);
</code></pre>
<p>The code snippet above will import <code>ethers</code> from Hardhat, <code>expect</code> from Chai for assertions, and <code>anyValue</code> for an event matching with arbitrary values.</p>
<h3 id="heading-setting-up-the-contract-instances-with-beforeeach">Setting up the contract instances with <code>beforeEach</code></h3>
<p>Before you dive into individual test cases, deploy the contracts to set up the environment. The <code>beforeEach</code> hook ensures that you have fresh instances of your contracts before every test case.</p>
<pre><code class="lang-jsx"><span class="hljs-comment">//...</span>

describe(<span class="hljs-string">"CrossChainGovernor"</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">let</span> governanceToken,
    crossChainGovernor,
    mockAxelarGateway,
    mockAxelarGasService,
    interchainProposalSender,
    thresholdContract;
  <span class="hljs-keyword">let</span> owner, addr1, addr2;

  beforeEach(<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
    [owner, addr1, addr2] = <span class="hljs-keyword">await</span> ethers.getSigners();

    <span class="hljs-keyword">const</span> GovernanceToken = <span class="hljs-keyword">await</span> ethers.getContractFactory(<span class="hljs-string">"GovernanceToken"</span>);
    governanceToken = <span class="hljs-keyword">await</span> GovernanceToken.deploy(owner.address);

    <span class="hljs-keyword">const</span> MockAxelarGateway = <span class="hljs-keyword">await</span> ethers.getContractFactory(<span class="hljs-string">"MockAxelarGateway"</span>);
    mockAxelarGateway = <span class="hljs-keyword">await</span> MockAxelarGateway.deploy();

    <span class="hljs-keyword">const</span> MockAxelarGasService = <span class="hljs-keyword">await</span> ethers.getContractFactory(<span class="hljs-string">"MockAxelarGasService"</span>);
    mockAxelarGasService = <span class="hljs-keyword">await</span> MockAxelarGasService.deploy();

    <span class="hljs-keyword">const</span> InterchainProposalSender = <span class="hljs-keyword">await</span> ethers.getContractFactory(<span class="hljs-string">"InterchainProposalSender"</span>);
    interchainProposalSender = <span class="hljs-keyword">await</span> InterchainProposalSender.deploy(mockAxelarGateway.address, mockAxelarGasService.address);

    <span class="hljs-keyword">const</span> ThresholdContract = <span class="hljs-keyword">await</span> ethers.getContractFactory(<span class="hljs-string">"ThresholdContract"</span>);
    thresholdContract = <span class="hljs-keyword">await</span> ThresholdContract.deploy();

    <span class="hljs-keyword">const</span> CrossChainGovernor = <span class="hljs-keyword">await</span> ethers.getContractFactory(<span class="hljs-string">"CrossChainGovernor"</span>);
    crossChainGovernor = <span class="hljs-keyword">await</span> CrossChainGovernor.deploy(
      <span class="hljs-string">"CrossChainGovernor"</span>,
      governanceToken.address,
      mockAxelarGateway.address,
      mockAxelarGasService.address,
      interchainProposalSender.address
    );

    <span class="hljs-keyword">await</span> governanceToken.delegate(owner.address);
    <span class="hljs-keyword">await</span> governanceToken.transfer(addr1.address, ethers.utils.parseEther(<span class="hljs-string">"100"</span>));
    <span class="hljs-keyword">await</span> governanceToken.connect(addr1).delegate(addr1.address);
    <span class="hljs-keyword">await</span> governanceToken.mint(owner.address, ethers.utils.parseEther(<span class="hljs-string">"1000000"</span>));

    <span class="hljs-keyword">await</span> ethers.provider.send(<span class="hljs-string">"evm_mine"</span>, []);
  });
});
</code></pre>
<p>This <code>beforeEach</code> function deploys new instances of the contracts, sets up the necessary addresses, and mints tokens for testing.</p>
<h4 id="heading-run-the-deployment-tests">Run the deployment tests</h4>
<p>Let's start by testing if the contracts are deployed correctly and with the correct parameters.</p>
<pre><code class="lang-jsx"><span class="hljs-comment">//...</span>

describe(<span class="hljs-string">"CrossChainGovernor"</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{

<span class="hljs-comment">//...</span>

    describe(<span class="hljs-string">"Deployment"</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
          it(<span class="hljs-string">"Should set the right token"</span>, <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
            expect(<span class="hljs-keyword">await</span> crossChainGovernor.token()).to.equal(governanceToken.address);
          });

          it(<span class="hljs-string">"Should set the right gas service"</span>, <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
            expect(<span class="hljs-keyword">await</span> crossChainGovernor.gasService()).to.equal(mockAxelarGasService.address);
          });

          it(<span class="hljs-string">"Should set the right proposal sender"</span>, <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
            expect(<span class="hljs-keyword">await</span> crossChainGovernor.proposalSender()).to.equal(interchainProposalSender.address);
          });
        });
});
</code></pre>
<p>To test the deployment, run the following command:</p>
<pre><code class="lang-bash">npx hardhat <span class="hljs-built_in">test</span>
</code></pre>
<pre><code class="lang-bash">  CrossChainGovernor
    Deployment
      ✔ Should <span class="hljs-built_in">set</span> the right token
      ✔ Should <span class="hljs-built_in">set</span> the right gas service
      ✔ Should <span class="hljs-built_in">set</span> the right proposal sender

  3 passing (2s)
</code></pre>
<h4 id="heading-testing-governance-settings">Testing governance settings</h4>
<p>Test the governance settings, including voting delay, voting period, and quorum.</p>
<pre><code class="lang-jsx"><span class="hljs-comment">//...</span>

describe(<span class="hljs-string">"CrossChainGovernor"</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{

<span class="hljs-comment">//...</span>

        describe(<span class="hljs-string">"Governance settings"</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
          it(<span class="hljs-string">"Should have the correct voting delay"</span>, <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
            expect(<span class="hljs-keyword">await</span> crossChainGovernor.votingDelay()).to.equal(<span class="hljs-number">1</span>);
          });

          it(<span class="hljs-string">"Should have the correct voting period"</span>, <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
            expect(<span class="hljs-keyword">await</span> crossChainGovernor.votingPeriod()).to.equal(<span class="hljs-number">50400</span>);
          });

          it(<span class="hljs-string">"Should have the correct quorum"</span>, <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
            expect(<span class="hljs-keyword">await</span> crossChainGovernor.quorum(<span class="hljs-number">0</span>)).to.equal(ethers.utils.parseEther(<span class="hljs-string">"1"</span>));
          });
        });
});
</code></pre>
<p>Run this test with the following command:</p>
<pre><code class="lang-bash">npx hardhat <span class="hljs-built_in">test</span>
</code></pre>
<pre><code class="lang-bash">  CrossChainGovernor
    Deployment
      ✔ Should <span class="hljs-built_in">set</span> the right token
      ✔ Should <span class="hljs-built_in">set</span> the right gas service
      ✔ Should <span class="hljs-built_in">set</span> the right proposal sender
    Governance settings
      ✔ Should have the correct voting delay
      ✔ Should have the correct voting period
      ✔ Should have the correct quorum

  6 passing (2s)
</code></pre>
<h4 id="heading-test-whitelisting-functionality">Test whitelisting functionality</h4>
<p>Test whether you can whitelist a proposal sender.</p>
<pre><code class="lang-jsx"><span class="hljs-comment">//...</span>

describe(<span class="hljs-string">"CrossChainGovernor"</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{

<span class="hljs-comment">//...</span>

        describe(<span class="hljs-string">"Whitelisting"</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
          it(<span class="hljs-string">"Should allow whitelisting a proposal sender"</span>, <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
            <span class="hljs-keyword">const</span> destinationChain = <span class="hljs-string">"destinationChain"</span>;
            <span class="hljs-keyword">const</span> destinationContract = thresholdContract.address;
            <span class="hljs-keyword">const</span> newThreshold = <span class="hljs-number">1000</span>;

            <span class="hljs-keyword">const</span> proposeTx = <span class="hljs-keyword">await</span> crossChainGovernor.proposeThresholdUpdate(
              destinationChain,
              destinationContract,
              thresholdContract.address,
              newThreshold
            );

            <span class="hljs-keyword">const</span> proposeReceipt = <span class="hljs-keyword">await</span> proposeTx.wait();

            <span class="hljs-keyword">await</span> expect(proposeTx)
              .to.emit(crossChainGovernor, <span class="hljs-string">"ThresholdProposalCreated"</span>)
              .withArgs(anyValue, destinationChain, destinationContract, thresholdContract.address, newThreshold);
          });
        });
});
</code></pre>
<p>To test the whitelisting functionality, run the following command:</p>
<pre><code class="lang-bash">npx hardhat <span class="hljs-built_in">test</span>
</code></pre>
<pre><code class="lang-bash">CrossChainGovernor
    Deployment
      ✔ Should <span class="hljs-built_in">set</span> the right token
      ✔ Should <span class="hljs-built_in">set</span> the right gas service
      ✔ Should <span class="hljs-built_in">set</span> the right proposal sender
    Governance settings
      ✔ Should have the correct voting delay
      ✔ Should have the correct voting period
      ✔ Should have the correct quorum
    Whitelisting
      ✔ Should allow whitelisting a proposal sender

  7 passing (2s)
</code></pre>
<h4 id="heading-testing-threshold-proposals">Testing Threshold proposals</h4>
<p>You can now test the creation and voting on threshold proposals.</p>
<pre><code class="lang-jsx"><span class="hljs-comment">//...</span>

describe(<span class="hljs-string">"CrossChainGovernor"</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{

<span class="hljs-comment">//...</span>

    describe(<span class="hljs-string">"Threshold Proposal"</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
      it(<span class="hljs-string">"Should allow creating a threshold proposal"</span>, <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
        <span class="hljs-keyword">const</span> destinationChain = <span class="hljs-string">"destinationChain"</span>;
        <span class="hljs-keyword">const</span> destinationContract = thresholdContract.address;
        <span class="hljs-keyword">const</span> newThreshold = <span class="hljs-number">1000</span>;

        <span class="hljs-keyword">await</span> expect(
          crossChainGovernor.proposeThresholdUpdate(
            destinationChain,
            destinationContract,
            thresholdContract.address,
            newThreshold
          )
        )
          .to.emit(crossChainGovernor, <span class="hljs-string">"ThresholdProposalCreated"</span>)
          .withArgs(anyValue, destinationChain, destinationContract, anyValue, newThreshold);
      });

      it(<span class="hljs-string">"Should allow voting on a threshold proposal"</span>, <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
        <span class="hljs-keyword">const</span> destinationChain = <span class="hljs-string">"destinationChain"</span>;
        <span class="hljs-keyword">const</span> destinationContract = thresholdContract.address;
        <span class="hljs-keyword">const</span> newThreshold = <span class="hljs-number">1000</span>;

        <span class="hljs-keyword">const</span> proposeTx = <span class="hljs-keyword">await</span> crossChainGovernor.proposeThresholdUpdate(
          destinationChain,
          destinationContract,
          thresholdContract.address,
          newThreshold
        );
        <span class="hljs-keyword">const</span> proposeReceipt = <span class="hljs-keyword">await</span> proposeTx.wait();

        <span class="hljs-keyword">const</span> proposalId = proposeReceipt.events.find(<span class="hljs-function"><span class="hljs-params">e</span> =&gt;</span> e.event === <span class="hljs-string">"ThresholdProposalCreated"</span>).args.proposalId;

        <span class="hljs-keyword">await</span> ethers.provider.send(<span class="hljs-string">"evm_mine"</span>, []);

        <span class="hljs-keyword">await</span> expect(crossChainGovernor.castVote(proposalId, <span class="hljs-number">1</span>)).to.emit(crossChainGovernor, <span class="hljs-string">"VoteCast"</span>);
      });
    });

});
</code></pre>
<p>Test the Threshold proposals by running the command below:</p>
<pre><code class="lang-bash">npx hardhat <span class="hljs-built_in">test</span>
</code></pre>
<pre><code class="lang-bash">CrossChainGovernor
    Deployment
      ✔ Should <span class="hljs-built_in">set</span> the right token
      ✔ Should <span class="hljs-built_in">set</span> the right gas service
      ✔ Should <span class="hljs-built_in">set</span> the right proposal sender
    Governance settings
      ✔ Should have the correct voting delay
      ✔ Should have the correct voting period
      ✔ Should have the correct quorum
    Whitelisting
      ✔ Should allow whitelisting a proposal sender
    Threshold Proposal
      ✔ Should allow creating a threshold proposal
      ✔ Should allow voting on a threshold proposal (13069ms)

  9 passing (16s)
</code></pre>
<h4 id="heading-testing-proposal-lifecycle">Testing proposal lifecycle</h4>
<p>Test the full lifecycle of a proposal, including its state transitions.</p>
<pre><code class="lang-jsx"><span class="hljs-comment">//...</span>

describe(<span class="hljs-string">"CrossChainGovernor"</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{

<span class="hljs-comment">//...</span>

        describe(<span class="hljs-string">"Proposal lifecycle"</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
          <span class="hljs-keyword">let</span> proposalId;

          beforeEach(<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
            <span class="hljs-keyword">const</span> destinationChain = <span class="hljs-string">"destinationChain"</span>;
            <span class="hljs-keyword">const</span> destinationContract = thresholdContract.address;
            <span class="hljs-keyword">const</span> newThreshold = <span class="hljs-number">1000</span>;

            <span class="hljs-keyword">const</span> proposeTx = <span class="hljs-keyword">await</span> crossChainGovernor.proposeThresholdUpdate(
              destinationChain,
              destinationContract,
              thresholdContract.address,
              newThreshold
            );

            <span class="hljs-keyword">const</span> proposeReceipt = <span class="hljs-keyword">await</span> proposeTx.wait();
            proposalId = proposeReceipt.events.find(<span class="hljs-function"><span class="hljs-params">e</span> =&gt;</span> e.event === <span class="hljs-string">"ThresholdProposalCreated"</span>).args.proposalId;

            <span class="hljs-keyword">await</span> ethers.provider.send(<span class="hljs-string">"evm_mine"</span>, []);
          });

          it(<span class="hljs-string">"Should start in the Pending state"</span>, <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
            <span class="hljs-keyword">const</span> proposalState = <span class="hljs-keyword">await</span> crossChainGovernor.state(proposalId);
            expect(proposalState).to.equal(<span class="hljs-number">0</span>); <span class="hljs-comment">// Pending</span>
          });

          it(<span class="hljs-string">"Should move to Active state after votingDelay"</span>, <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
            <span class="hljs-keyword">await</span> ethers.provider.send(<span class="hljs-string">"evm_mine"</span>, []);
            <span class="hljs-keyword">const</span> proposalState = <span class="hljs-keyword">await</span> crossChainGovernor.state(proposalId);
            expect(proposalState).to.equal(<span class="hljs-number">1</span>); <span class="hljs-comment">// Active</span>
          });

          it(<span class="hljs-string">"Should allow voting when Active"</span>, <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
            <span class="hljs-keyword">await</span> expect(crossChainGovernor.castVote(proposalId, <span class="hljs-number">1</span>)).to.emit(crossChainGovernor, <span class="hljs-string">"VoteCast"</span>);
          });
        });
    });
</code></pre>
<p>Run:</p>
<pre><code class="lang-bash">npx hardhat <span class="hljs-built_in">test</span>
</code></pre>
<h4 id="heading-testing-proposal-execution">Testing proposal execution</h4>
<p>Lastly, ensure that proposals are only executed when successful.</p>
<pre><code class="lang-jsx"><span class="hljs-comment">//...</span>

describe(<span class="hljs-string">"CrossChainGovernor"</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{

<span class="hljs-comment">//...</span>

        describe(<span class="hljs-string">"Proposal Execution"</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
          it(<span class="hljs-string">"Should allow execution of a succeeded proposal"</span>, <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
            <span class="hljs-keyword">const</span> proposalId = anyValue;
            <span class="hljs-keyword">const</span> gasFee = ethers.utils.parseEther(<span class="hljs-string">"0.1"</span>);
            <span class="hljs-keyword">await</span> expect(
              crossChainGovernor.executeThresholdProposal(proposalId, {
                <span class="hljs-attr">value</span>: gasFee,
              })
            ).to.emit(crossChainGovernor, <span class="hljs-string">"ThresholdProposalExecuted"</span>);
          });

          it(<span class="hljs-string">"Should not allow execution of an already executed proposal"</span>, <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
            <span class="hljs-keyword">const</span> proposalId = anyValue;
            <span class="hljs-keyword">const</span> gasFee = ethers.utils.parseEther(<span class="hljs-string">"0.1"</span>);
            <span class="hljs-keyword">await</span> crossChainGovernor.executeThresholdProposal(proposalId, {
              <span class="hljs-attr">value</span>: gasFee,
            });

            <span class="hljs-keyword">await</span> expect(
              crossChainGovernor.executeThresholdProposal(proposalId, {
                <span class="hljs-attr">value</span>: gasFee,
              })
            ).to.be.revertedWith(<span class="hljs-string">"Proposal must be succeeded"</span>);
          });
        });

});
</code></pre>
<p>Run the proposal execution test using the following command:</p>
<pre><code class="lang-bash">npx hardhat <span class="hljs-built_in">test</span>
</code></pre>
<pre><code class="lang-bash">CrossChainGovernor
    Deployment
      ✔ Should <span class="hljs-built_in">set</span> the right token
      ✔ Should <span class="hljs-built_in">set</span> the right gas service
      ✔ Should <span class="hljs-built_in">set</span> the right proposal sender
    Governance settings
      ✔ Should have the correct voting delay
      ✔ Should have the correct voting period
      ✔ Should have the correct quorum
    Whitelisting
      ✔ Should allow whitelisting a proposal sender
    Threshold Proposal
      ✔ Should allow creating a threshold proposal
      ✔ Should allow voting on a threshold proposal (13203ms)
    Proposal lifecycle
      ✔ Should start <span class="hljs-keyword">in</span> the Pending state
      ✔ Should move to Active state after votingDelay
      ✔ Should allow voting when Active
    Proposal Execution
      ✔ Should not allow execution of a proposal that hasn<span class="hljs-string">'t succeeded (42ms)
      ✔ Should allow execution of a succeeded proposal (13341ms)
      ✔ Should not allow execution of an already executed proposal (13399ms)

  15 passing (44s)</span>
</code></pre>
<h4 id="heading-proposal-creation-and-voting">Proposal creation and voting</h4>
<p>This section covers how to test the creation of proposals by token and non-token holders, ensure proper voting behavior, and prevent double voting.</p>
<h4 id="heading-test-for-non-token-holders-creating-proposals">Test for non-token holders creating proposals</h4>
<p>In this test, we check if non-token holders can create proposals. However, the proposal should fail due to a lack of quorum.</p>
<pre><code class="lang-jsx"><span class="hljs-comment">//...</span>
describe(<span class="hljs-string">"CrossChainGovernor"</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{

<span class="hljs-comment">//...</span>

        describe(<span class="hljs-string">"Proposal Creation and Voting"</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{

                it(<span class="hljs-string">"Should allow non-token holders to create proposals, but the proposal should fail"</span>, <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
                  <span class="hljs-keyword">const</span> [, nonHolder] = <span class="hljs-keyword">await</span> ethers.getSigners();

                  <span class="hljs-comment">// Create a proposal</span>
                  <span class="hljs-keyword">const</span> tx = <span class="hljs-keyword">await</span> crossChainGovernor
                    .connect(nonHolder)
                    .proposeThresholdUpdate(
                      <span class="hljs-string">"destinationChain"</span>,
                      crossChainGovernor.address,
                      thresholdContract.address,
                      <span class="hljs-number">1000</span>
                    );

                  <span class="hljs-keyword">const</span> receipt = <span class="hljs-keyword">await</span> tx.wait();
                  <span class="hljs-keyword">const</span> event = receipt.events.find(
                    <span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> e.event === <span class="hljs-string">"ThresholdProposalCreated"</span>
                  );
                  expect(event).to.not.be.undefined;

                  <span class="hljs-keyword">const</span> proposalId = event.args.proposalId;

                  <span class="hljs-comment">// Advance the block to move past the voting delay</span>
                  <span class="hljs-keyword">const</span> votingDelay = <span class="hljs-keyword">await</span> crossChainGovernor.votingDelay();
                  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt;= votingDelay.toNumber(); i++) {
                    <span class="hljs-keyword">await</span> ethers.provider.send(<span class="hljs-string">"evm_mine"</span>, []); <span class="hljs-comment">// Mine blocks</span>
                  }

                  <span class="hljs-comment">// Let the proposal become active and fail due to insufficient quorum</span>
                  <span class="hljs-keyword">const</span> votingPeriod = <span class="hljs-keyword">await</span> crossChainGovernor.votingPeriod();
                  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt;= votingPeriod.toNumber(); i++) {
                    <span class="hljs-keyword">await</span> ethers.provider.send(<span class="hljs-string">"evm_mine"</span>, []); <span class="hljs-comment">// Advance to the end of the voting period</span>
                  }

                  <span class="hljs-comment">// Check if the proposal state is defeated (3) due to lack of quorum</span>
                  <span class="hljs-keyword">const</span> newProposalState = <span class="hljs-keyword">await</span> crossChainGovernor.state(proposalId);
                  expect(newProposalState).to.equal(<span class="hljs-number">3</span>); <span class="hljs-comment">// State 3 is Defeated</span>
                });
    });

});
</code></pre>
<h4 id="heading-test-voting-before-voting-delay-has-passed">Test voting before voting delay has passed</h4>
<p>This test ensures that voting cannot occur before the voting delay set by the governance process.</p>
<pre><code class="lang-jsx">
<span class="hljs-comment">//...</span>

it(<span class="hljs-string">"Should not allow voting before the voting delay has passed"</span>, <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
  <span class="hljs-comment">// First, create a proposal to get a valid proposalId</span>
  <span class="hljs-keyword">const</span> tx = <span class="hljs-keyword">await</span> crossChainGovernor.proposeThresholdUpdate(
    <span class="hljs-string">"destinationChain"</span>,
    crossChainGovernor.address,
    thresholdContract.address,
    <span class="hljs-number">1000</span>
  );

  <span class="hljs-comment">// Wait for the transaction to be mined and get the event logs</span>
  <span class="hljs-keyword">const</span> receipt = <span class="hljs-keyword">await</span> tx.wait();
  <span class="hljs-keyword">const</span> event = receipt.events.find(
    <span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> e.event === <span class="hljs-string">"ThresholdProposalCreated"</span>
  );

  <span class="hljs-comment">// Ensure the event exists and extract the proposalId</span>
  <span class="hljs-keyword">if</span> (!event) {
    <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"ThresholdProposalCreated event not found"</span>);
  }
  <span class="hljs-keyword">const</span> proposalId = event.args.proposalId;

  <span class="hljs-comment">// Now try to cast a vote before the voting delay has passed</span>
  <span class="hljs-keyword">await</span> expect(
    crossChainGovernor.castVote(proposalId, <span class="hljs-number">1</span>)
  ).to.be.revertedWith(<span class="hljs-string">"Governor: vote not currently active"</span>);
});

<span class="hljs-comment">//...</span>
</code></pre>
<h4 id="heading-test-voting-after-voting-period-has-ended">Test voting after voting period has ended</h4>
<p>This test ensures no voting can happen after the designated voting period ends.</p>
<pre><code class="lang-jsx"><span class="hljs-comment">//...</span>

it(<span class="hljs-string">"Should not allow voting after the voting period has ended"</span>, <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
  <span class="hljs-comment">// First, create a proposal to get a valid proposalId</span>
  <span class="hljs-keyword">const</span> tx = <span class="hljs-keyword">await</span> crossChainGovernor.proposeThresholdUpdate(
    <span class="hljs-string">"destinationChain"</span>,
    crossChainGovernor.address,
    thresholdContract.address,
    <span class="hljs-number">1000</span>
  );

  <span class="hljs-keyword">const</span> receipt = <span class="hljs-keyword">await</span> tx.wait();
  <span class="hljs-keyword">const</span> event = receipt.events.find(
    <span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> e.event === <span class="hljs-string">"ThresholdProposalCreated"</span>
  );

  <span class="hljs-keyword">if</span> (!event) {
    <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"ThresholdProposalCreated event not found"</span>);
  }
  <span class="hljs-keyword">const</span> proposalId = event.args.proposalId;

  <span class="hljs-comment">// Wait for the voting period to pass</span>
  <span class="hljs-keyword">const</span> votingPeriod = <span class="hljs-keyword">await</span> crossChainGovernor.votingPeriod();
  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt;= votingPeriod.toNumber(); i++) {
    <span class="hljs-keyword">await</span> ethers.provider.send(<span class="hljs-string">"evm_mine"</span>, []);
  }

  <span class="hljs-comment">// Now try to vote after the voting period has ended</span>
  <span class="hljs-keyword">await</span> expect(
    crossChainGovernor.castVote(proposalId, <span class="hljs-number">1</span>)
  ).to.be.revertedWith(<span class="hljs-string">"Governor: vote not currently active"</span>);
});
</code></pre>
<h4 id="heading-test-double-voting-prevention">Test double voting prevention</h4>
<p>This test ensures that voters cannot cast more than one vote on the same proposal.</p>
<pre><code class="lang-jsx"><span class="hljs-comment">//...</span>

it(<span class="hljs-string">"Should not allow double voting"</span>, <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
  <span class="hljs-comment">// First, create a proposal to get a valid proposalId</span>
  <span class="hljs-keyword">const</span> tx = <span class="hljs-keyword">await</span> crossChainGovernor.proposeThresholdUpdate(
    <span class="hljs-string">"destinationChain"</span>,
    crossChainGovernor.address,
    thresholdContract.address,
    <span class="hljs-number">1000</span>
  );

  <span class="hljs-keyword">const</span> receipt = <span class="hljs-keyword">await</span> tx.wait();
  <span class="hljs-keyword">const</span> event = receipt.events.find(
    <span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> e.event === <span class="hljs-string">"ThresholdProposalCreated"</span>
  );

  <span class="hljs-keyword">if</span> (!event) {
    <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"ThresholdProposalCreated event not found"</span>);
  }
  <span class="hljs-keyword">const</span> proposalId = event.args.proposalId;

  <span class="hljs-comment">// Move forward to the voting period</span>
  <span class="hljs-keyword">const</span> votingDelay = <span class="hljs-keyword">await</span> crossChainGovernor.votingDelay();
  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt;= votingDelay.toNumber(); i++) {
    <span class="hljs-keyword">await</span> ethers.provider.send(<span class="hljs-string">"evm_mine"</span>, []);
  }

  <span class="hljs-comment">// Cast the first vote</span>
  <span class="hljs-keyword">await</span> crossChainGovernor.castVote(proposalId, <span class="hljs-number">1</span>);

  <span class="hljs-comment">// Now attempt to cast a second vote, which should fail</span>
  <span class="hljs-keyword">await</span> expect(
    crossChainGovernor.castVote(proposalId, <span class="hljs-number">1</span>)
  ).to.be.revertedWith(<span class="hljs-string">"GovernorVotingSimple: vote already cast"</span>);
})
</code></pre>
<h3 id="heading-running-all-the-tests">Running all the tests</h3>
<p>After adding the above tests, you can run all tests in the <code>CrossChainGovernor.test.js</code> file by executing the following command:</p>
<pre><code class="lang-bash">npx hardhat <span class="hljs-built_in">test</span>
</code></pre>
<pre><code class="lang-bash">CrossChainGovernor
    Deployment
      ✔ Should <span class="hljs-built_in">set</span> the right token
      ✔ Should <span class="hljs-built_in">set</span> the right gas service
      ✔ Should <span class="hljs-built_in">set</span> the right proposal sender
    Governance settings
      ✔ Should have the correct voting delay
      ✔ Should have the correct voting period
      ✔ Should have the correct quorum
    Whitelisting
      ✔ Should allow whitelisting a proposal sender
    Threshold Proposal
      ✔ Should allow creating a threshold proposal
      ✔ Should allow voting on a threshold proposal (113ms)
    Proposal lifecycle
      ✔ Should start <span class="hljs-keyword">in</span> the Pending state
      ✔ Should move to Active state after votingDelay
      ✔ Should allow voting when Active
    Proposal Creation and Voting
      ✔ Should allow non-token holders to create proposals, but the proposal should fail (13098ms)
      ✔ Should not allow voting before the voting delay has passed (46ms)
      ✔ Should not allow voting after the voting period has ended (166ms)
      ✔ Should not allow double voting (39ms)
    Proposal Execution
      ✔ Should not allow execution of a proposal that hasn<span class="hljs-string">'t succeeded
      ✔ Should allow execution of a succeeded proposal (139ms)
      ✔ Should not allow execution of an already executed proposal (189ms)

  19 passing (1m)</span>
</code></pre>
<p>Congratulations 🥳 all the tests passed.</p>
<h2 id="heading-next-steps">Next Steps</h2>
<p>This example builds directly on Axelar's <a target="_blank" href="https://github.com/axelarnetwork/interchain-governance-orchestrator">Interchain Governance Orchestrator</a>, making it straightforward to integrate with the OpenZeppelin Governor for cross-chain governance. With these tools, you can easily manage governance across multiple blockchains.</p>
<p>To move forward, try deploying your contracts on <a target="_blank" href="https://docs.axelar.dev/resources/contract-addresses/testnet/">testnets supported by Axelar</a>. This will help you test the system in a real-world environment. You can also explore more advanced features like cross-chain token transfers and contract calls through Axelar's <a target="_blank" href="https://docs.axelar.dev/dev/general-message-passing/overview">General Message Passing</a>.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this tutorial, you learned how to build and test the <code>CrossChainGovernor</code> contract using OpenZepplin and Axelar General Message Passing. From testing deployments, governance settings, and whitelisting to proposal lifecycles and execution, you've covered all the essential aspects.</p>
<h2 id="heading-references">References</h2>
<ul>
<li><p><a target="_blank" href="https://docs.openzeppelin.com/contracts/4.x/governance">OpenZeppelin Governance Docs</a></p>
</li>
<li><p><a target="_blank" href="https://www.axelar.network/blog/uniswap-filecoin-bridge-cross-chain-governance">Bridging Uniswap &amp; Filecoin: A Cross-Chain Governance Case Study</a></p>
</li>
<li><p><a target="_blank" href="https://docs.axelar.dev/dev/axelarjs/send-message"><strong>Axelar General Message Passing (GMP</strong></a><strong>)</strong></p>
</li>
<li><p><a target="_blank" href="https://hardhat.org/getting-started">Hardhat Documentation</a></p>
</li>
<li><p><a target="_blank" href="https://github.com/NomicFoundation/hardhat/tree/master/packages/hardhat-chai-matchers">Hardhat Chai Matchers</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Foundry Axelar GMP Example Now Supports Interchain Token Service (ITS) Integration]]></title><description><![CDATA[We're excited to announce that the Foundry Axelar GMP Example repository now features integration with Axelar's Interchain Token Service (ITS). This update empowers developers to build cross-chain applications more efficiently, simplifying the deploy...]]></description><link>https://blog.axelar.dev/foundry-axelar-gmp-example-now-supports-interchain-token-service-its-integration</link><guid isPermaLink="true">https://blog.axelar.dev/foundry-axelar-gmp-example-now-supports-interchain-token-service-its-integration</guid><category><![CDATA[axelar]]></category><category><![CDATA[foundry]]></category><category><![CDATA[Smart Contracts]]></category><category><![CDATA[Blockchain]]></category><category><![CDATA[Web3]]></category><category><![CDATA[Solidity]]></category><dc:creator><![CDATA[Idris Olubisi]]></dc:creator><pubDate>Wed, 18 Sep 2024 14:23:40 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1727225621725/f2e2a74f-91a1-4edb-8264-746bbbed1f9e.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>We're excited to announce that the <a target="_blank" href="https://github.com/axelarnetwork/foundry-axelar-gmp-example">Foundry Axelar GMP Example</a> repository now features integration with <a target="_blank" href="https://docs.axelar.dev/dev/send-tokens/interchain-tokens/intro/">Axelar's Interchain Token Service (ITS)</a>. This update empowers developers to build cross-chain applications more efficiently, simplifying the deployment and interaction with interchain tokens.</p>
<h2 id="heading-what-is-the-interchain-token-service-its">What is the Interchain Token Service (ITS)?</h2>
<p>Axelar's <a target="_blank" href="https://docs.axelar.dev/dev/send-tokens/interchain-tokens/intro/">Interchain Token Service</a> allows developers to create and manage tokens that operate seamlessly across multiple blockchain networks. With ITS, you can deploy tokens that are natively cross-chain, eliminating the complexities of bridging and wrapping tokens manually.</p>
<p>ITS leverages sophisticated mechanisms to ensure tokens maintain their integrity and security across chains, offering a robust solution for developers looking to extend their tokens' reach beyond a single blockchain. It scales tokens to many chains, supporting existing and newly minted tokens, preserving native-like fungibility and functionality on connected EVM chains, and automating deployment and maintenance so teams can easily manage supply.</p>
<h2 id="heading-whats-new-in-the-repository">What's New in the Repository?</h2>
<p>We've added several new examples to help you get started with ITS:</p>
<ul>
<li><p><a target="_blank" href="https://github.com/axelarnetwork/foundry-axelar-gmp-example/blob/main/src/its-interchain-token"><strong>New Interchain Token Example</strong></a>: Learn how to deploy a brand-new interchain token using ITS.</p>
</li>
<li><p><a target="_blank" href="https://github.com/axelarnetwork/foundry-axelar-gmp-example/blob/main/src/its-canonical-token"><strong>Canonical Token Deployment Example</strong></a>: Discover how to deploy a canonical token that serves as a single source of truth across chains.</p>
</li>
<li><p><a target="_blank" href="https://github.com/axelarnetwork/foundry-axelar-gmp-example/blob/main/src/its-interchain-token"><strong>Interchain Custom Token Example</strong></a>: Explore how to create and interact with custom tokens with interchain functionality.</p>
</li>
</ul>
<p>You can check out the updated repository here: <a target="_blank" href="https://github.com/axelarnetwork/foundry-axelar-gmp-example">Foundry Axelar GMP Example</a></p>
<h2 id="heading-how-does-this-benefit-you">How Does This Benefit You?</h2>
<p>By integrating ITS into the Foundry Axelar GMP example, we've made it simpler for you to:</p>
<ul>
<li><p><strong>Develop Multichain Tokens</strong>: Easily create tokens that work across different blockchain networks without dealing with multiple codebases.</p>
</li>
<li><p><strong>Simplify Cross-Chain Interactions</strong>: Use Axelar's General Message Passing (GMP) to interact with contracts on other chains effortlessly.</p>
</li>
<li><p><strong>Accelerate Development</strong>: Utilize ready-made examples and scripts to speed up your development process.</p>
</li>
</ul>
<h2 id="heading-getting-started">Getting Started</h2>
<ol>
<li><p><strong>Clone the Repository</strong>:</p>
<p> Begin by cloning the Foundry Axelar GMP Example repository.</p>
<pre><code class="lang-bash"> git <span class="hljs-built_in">clone</span> https://github.com/axelarnetwork/foundry-axelar-gmp-example
</code></pre>
</li>
<li><p><strong>Navigate into the Project Directory</strong>:</p>
<pre><code class="lang-bash"> <span class="hljs-built_in">cd</span> foundry-axelar-gmp-example
</code></pre>
</li>
<li><p><strong>Install Dependencies</strong>:</p>
<p> Run the following command to install all dependencies and build the project:</p>
<pre><code class="lang-bash"> make all
</code></pre>
<p> This command will:</p>
<ul>
<li><p>Install the necessary dependencies.</p>
</li>
<li><p>Create a <code>.env</code> file from <code>.env.example</code>.</p>
</li>
<li><p>Build and update the project.</p>
</li>
</ul>
</li>
<li><p><strong>Start Local Chains</strong>:</p>
<p> To test Axelar GMP locally, start local blockchain networks:</p>
<pre><code class="lang-bash"> make local-chain-start
</code></pre>
<p> Leave this running in a separate terminal.</p>
</li>
<li><p><strong>Deploy Contracts</strong>:</p>
<p> Deploy the contracts to the local chains:</p>
<pre><code class="lang-bash"> make local-chain-deploy
</code></pre>
</li>
<li><p><strong>Execute Contracts</strong>:</p>
<p> Now you can test General Message Passing (GMP) and other features:</p>
<pre><code class="lang-bash"> make local-chain-execute
</code></pre>
</li>
</ol>
<h2 id="heading-features">Features</h2>
<p>We've included a set of <code>Makefile</code> Commands to streamline your workflow:</p>
<ul>
<li><p><code>make all</code>: Install dependencies, build, and update the project.</p>
</li>
<li><p><code>make setup-env</code>: Create a <code>.env</code> file from <code>.env.example</code>.</p>
</li>
<li><p><code>make install</code>: Install all dependencies.</p>
</li>
<li><p><code>make build</code>: Compile the smart contracts.</p>
</li>
<li><p><code>make update</code>: Pull the latest updates for the project.</p>
</li>
<li><p><code>make deploy</code>: Deploy a specific contract to a specified network.</p>
</li>
<li><p><code>make execute</code>: Execute a function of a deployed contract on a specified network.</p>
</li>
<li><p><code>make format</code>: Format the codebase using Foundry's formatter.</p>
</li>
<li><p><code>make test</code>: Run tests with increased verbosity.</p>
</li>
<li><p><code>make clean</code>: Remove generated artifacts.</p>
</li>
<li><p><code>make rpc</code>: Display RPC URLs for various networks.</p>
</li>
<li><p><code>make help</code>: Display the help menu.</p>
</li>
<li><p><code>make local-chain-start</code>: Start local blockchain networks using Anvil.</p>
</li>
<li><p><code>make local-chain-deploy</code>: Deploy contracts to local chains.</p>
</li>
<li><p><code>make local-chain-execute</code>: Execute commands to test GMP with ITS.</p>
<h3 id="heading-interchain-token-service-its-commands-for-local-chains">Interchain Token Service (ITS) commands for local chains:</h3>
<ul>
<li><p><code>make deploy-interchain-token</code>: Deploy an interchain token on local chains.</p>
</li>
<li><p><code>make deploy-mint-burn-token-manager-and-transfer</code>: Set up token managers and perform a transfer on local chains.</p>
</li>
<li><p><code>make deploy-canonical-token</code>: Deploy a canonical token on local chains.</p>
</li>
<li><p><code>make help</code>: Display the help menu with available commands and descriptions.</p>
</li>
</ul>
</li>
</ul>
<h3 id="heading-interchain-token-service-its-commands-for-testnet">Interchain Token Service (ITS) commands for testnet:</h3>
<ul>
<li><p><code>make deploy-canonical-token-testnet</code>: Deploy and register a canonical token on testnet.</p>
</li>
<li><p><code>make transfer-canonical-token-testnet</code>: Perform interchain transfer of a canonical token on testnet.</p>
</li>
<li><p><code>make deploy-interchain-token-testnet</code>: Deploy an interchain token on testnet.</p>
</li>
<li><p><code>make transfer-interchain-token-testnet</code>: Perform interchain transfer of an interchain token on testnet.</p>
</li>
<li><p><code>make deploy-custom-token-testnet</code>: Deploy a custom token on testnet.</p>
</li>
<li><p><code>make transfer-custom-token-testnet</code>: Perform interchain transfer of a custom token on testnet.</p>
</li>
</ul>
<p>Check out the updated repository here: <a target="_blank" href="https://github.com/axelarnetwork/foundry-axelar-gmp-example">Foundry Axelar GMP Example</a>.</p>
<h2 id="heading-whats-next">What's Next?</h2>
<p>We encourage you to explore the new ITS features and build cross-chain applications. The updated examples are designed to help you grasp the concepts quickly and integrate them into your projects.</p>
<p><strong>Prefer Hardhat?</strong> Check out our <a target="_blank" href="https://github.com/axelarnetwork/axelar-examples">Axelar Examples repository</a> for more resources.</p>
<p>If you have any questions or need assistance, please open an issue in our <a target="_blank" href="https://github.com/axelarnetwork/axelar-support">support repository</a>. We're here to help!</p>
]]></content:encoded></item><item><title><![CDATA[August 2024 Dev Update: Interchain Amplifier Hits Testnet, OpenZeppelin Integration, Multichain RWA, Docs Update  🏗️]]></title><description><![CDATA[Welcome to the August 2024 Axelar Developer Newsletter. This month, Axelar takes giant leaps in cross-chain interoperability with our mainnet upgrade, Interchain Amplifier hitting testnet, and a collaboration with OpenZeppelin.

🆙 Axelar Network upg...]]></description><link>https://blog.axelar.dev/august-2024-interchain-amplifier-hits-testnet-openzeppelin-integration-multichain-rwa-docs-update</link><guid isPermaLink="true">https://blog.axelar.dev/august-2024-interchain-amplifier-hits-testnet-openzeppelin-integration-multichain-rwa-docs-update</guid><category><![CDATA[axelar]]></category><category><![CDATA[Developer]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[newsletter]]></category><category><![CDATA[Web3]]></category><dc:creator><![CDATA[Idris Olubisi]]></dc:creator><pubDate>Fri, 30 Aug 2024 16:54:24 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1725034543643/b7ea25b7-47ff-4570-b0e8-aed753f33e1b.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Welcome to the August 2024 Axelar Developer Newsletter. This month, Axelar takes giant leaps in cross-chain interoperability with our mainnet upgrade, Interchain Amplifier hitting testnet, and a collaboration with OpenZeppelin.</p>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXfD86WaBLGGGt2yRuFu_XlU9pBXRDQO-SfM-keU2l-yBISmdqIkWxbXcypFSCwoO9fRUqZkjqLFmaaUz7OVzNJvKlJmMQc8dFhJ_M30KPHLLAsjwIts6gp69SQF313i8wR9vP2o5w1W7-GNNOj88U9P81SH?key=iJIW6hzxF9rCKOtohDTIQA" alt /></p>
<h2 id="heading-axelar-network-upgrade-v102">🆙 Axelar Network upgrade: v1.0.2</h2>
<p>On August 28, 2024, we successfully upgraded our mainnet to v1.0.2, paving the way for exciting new features:</p>
<ul>
<li><p>Mainnet deployment for Amplifier</p>
</li>
<li><p>Enhanced stability and performance</p>
</li>
<li><p>New IBC-related queries for better chain connectivity</p>
</li>
<li><p>"BatchRequest" message type for granular transaction handling</p>
</li>
<li><p>Quick (de)activation of core-amplifier connections</p>
</li>
</ul>
<p>This release enabled mainnet deployment for <strong>Amplifier</strong> and included updates to <code>axelard</code>, <a target="_blank" href="https://github.com/axelarnetwork/axelar-core/releases/tag/v1.0.2"><code>vald (1.0.2)</code></a>, and <a target="_blank" href="https://github.com/axelarnetwork/tofnd/releases/tag/v1.0.1"><code>tofnd (1.0.1)</code></a>.</p>
<p>What this means for you: Faster, more reliable cross-chain operations and greater flexibility in managing your interchain applications.</p>
<p>Ready to upgrade? Check out our detailed <a target="_blank" href="https://docs.axelar.dev/resources/mainnet/upgrades/v1.0/">instructions and changelog</a>.</p>
<h2 id="heading-interchain-amplifier-now-on-testnet-coming-soon-to-mainnet">🔬 Interchain Amplifier: now on testnet, coming soon to mainnet</h2>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXddub0N_fn68D_BaVvhBbEKyBvw8VTmbPGOixGiGJEjx0iuwrnCf2fHaELFlZZdTErb0Vz7oL7gCdO66Wa8BAIeztAe_GyBrYuDleqggUkLigFWgib9xDsPe21YqxR2x1gGKz0IiCUan9B6vmEnpmudI8pr?key=iJIW6hzxF9rCKOtohDTIQA" alt /></p>
<p>The Interchain Amplifier has hit testnet, with mainnet deployment just around the corner. This feature offers:</p>
<ul>
<li><p>Seamless connection of diverse blockchain consensus engines</p>
</li>
<li><p>Integration with traditional off-chain systems</p>
</li>
<li><p>Minimal developer overhead</p>
</li>
</ul>
<p>Key components include:</p>
<ul>
<li><p>On-chain message router</p>
</li>
<li><p>Gateways</p>
</li>
<li><p>CosmWasm methods for bidirectional messaging</p>
</li>
</ul>
<p>What this means for you: Unprecedented flexibility in building cross-chain applications with reduced complexity.</p>
<p>Curious? <a target="_blank" href="https://docs.axelar.dev/dev/amplifier/introduction">Get started with Amplifier</a>.</p>
<h2 id="heading-openzeppelin-integration">🤝OpenZeppelin Integration</h2>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXdffJFUhAFM_a_Fyr_m35xEdLUN0YQdrvNi2t9MpKSWpndrWXp-onG8djo5Wc1R_67pJNcB6jTjTWFbuvH09MEQJynBZSgFqa6DqnOb-2WJXoYiRnA-A--Jos5CcpBuwtEsLsXabNES24L3ElVbB38Dx2MF?key=iJIW6hzxF9rCKOtohDTIQA" alt /></p>
<p>We're excited to announce that Axelar and OpenZeppelin are joining forces to solve Ethereum's interoperability challenges, especially with the rise of Layer 2 solutions. For you as a developer, this collaboration means:</p>
<ul>
<li><p>Standardized Solidity code for cross-chain messaging</p>
</li>
<li><p>Integration with OpenZeppelin's Contract Wizard</p>
</li>
<li><p>Simplified tools for building interchain contracts using Axelar</p>
</li>
</ul>
<p>Excited to learn more? <a target="_blank" href="https://x.com/axelar/status/1825887799796752636">Read the full announcement</a>.</p>
<h2 id="heading-new-tutorials-docs-and-more">📚 New tutorials, docs, and more</h2>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXfcuDTNj9_uLc2kDlXXFT1y96aWoVVLimXYBjfjXzeqxUxlBu2nThctv98m5f6s6xfv_L7FaxBcob5VkIYz-UWPCb5KsfViW7jdvdl6gbkOcsP7Degmk6Q8fbSbL-LpDF4m2CmwNnvTAwR4wRpBAFYSwn-r?key=iJIW6hzxF9rCKOtohDTIQA" alt /></p>
<p>We've just published several relevant technical articles and documentation updates.</p>
<h3 id="heading-amplifier">Amplifier</h3>
<ul>
<li><p><a target="_blank" href="https://docs.axelar.dev/dev/amplifier/roadmap/">Amplifier Roadmap</a>: Learn about what you'll be able to do with Amplifier now and in the future, as the Interop Labs team rolls out more features.</p>
</li>
<li><p><a target="_blank" href="https://docs.axelar.dev/dev/amplifier/chain-integration/relay-messages">Message Relaying with Amplifier</a>: Learn how to relay cross-chain messages using Axelar's Amplifier, from message verification to execution on the destination chain, with code examples provided for Avalanche and Ethereum Sepolia.</p>
</li>
<li><p><a target="_blank" href="https://docs.axelar.dev/validator/amplifier/verifier-security-expectations">Verifier Security Expectations</a><strong>:</strong> Learn about the security expectations for verifiers in the Axelar network, including running full nodes, maintaining uptime, rotating keys, pulling rewards, supporting trustworthy chains, and participating in security drills and escalations.</p>
</li>
<li><p><a target="_blank" href="https://docs.axelar.dev/dev/amplifier/add-rewards">Add rewards for Amplifier chain integrators</a>: Learn how to add funds to the rewards pool of an Amplifier-integrated chain.</p>
</li>
<li><p><a target="_blank" href="https://docs.axelar.dev/dev/amplifier/chain-integration/error-messages/">Common Amplifier Error Messages (Chain Integrators)</a>.</p>
</li>
<li><p><a target="_blank" href="https://docs.axelar.dev/validator/amplifier/error-messages/">Common Amplifier Error Messages (Verifiers / Relayers)</a>.</p>
</li>
</ul>
<h3 id="heading-its">ITS</h3>
<ul>
<li><p><a target="_blank" href="https://docs.moralis.io/web3-data-api/evm/integrations/Axelar/create-multichain-tokens">Create Multichain Tokens with Interchain Token Service</a>: Learn how to create a Multichain Token that is fungible and customizable across all blockchains.</p>
</li>
<li><p><a target="_blank" href="https://docs.moralis.io/web3-data-api/evm/integrations/Axelar/bridge-tokens-to-all-chains-with-ITS">Bridge your Existing ERC20 token to all chains with ITS using the Ethereum</a>: Learn how to programmatically create a Canonical Interchain Token from scratch using Interchain Token Service and the <strong>Ethereum Boilerplate.</strong></p>
</li>
<li><p><a target="_blank" href="https://moralis.io/how-to-mint-an-erc-20-token-on-base-with-the-interchain-token-service-in-5-steps/">How to Mint an ERC-20 Token on Base with the Interchain Token Service in 5 Steps:</a> This step-by-step guide will teach you how to mint a multichain ERC-20 token on the Base network using Axelar’s Interchain Token Service (ITS) and use the Moralis Token API to retrieve token balances easily.</p>
</li>
</ul>
<h3 id="heading-docs-updates">Docs Updates</h3>
<ul>
<li><p><a target="_blank" href="https://docs.axelar.dev/dev/cosmos-gmp/developer-guides/cross-chain-messaging-evm-to-cosmos">Cross-Chain Messaging: EVM to Cosmos</a>: Learn to enable cross-chain communication between EVM and Cosmos using Axelar's GMP. This tutorial covers deploying contracts on Avalanche and Osmosis, sending and receiving messages between them, and verifying transactions, allowing you to build interoperable dApps across both ecosystems.</p>
</li>
<li><p><a target="_blank" href="https://docs.axelar.dev/dev/gas-service/specify-gas-refund-address/">Specify the refund address for a contract call</a>: Learn how to specify a refund address for unused gas in Axelar's GMP.</p>
</li>
<li><p><a target="_blank" href="https://docs.axelar.dev/dev/gas-service/transaction-state">Transactions: Tracking and Retrying Failed States</a>: Learn how to track and recover failed blockchain transactions using Axelarscan and the AxelarJS SDK.</p>
</li>
<li><p><a target="_blank" href="https://docs.axelar.dev/dev/general-message-passing/axelar-commandid"><code>CommandID</code></a>: Learn about the <code>CommandID</code>, a unique identifier crucial for secure cross-chain communication, its role in message verification, and examples in Solidity and Go to prevent replay attacks and ensure message integrity.</p>
</li>
</ul>
<h2 id="heading-catch-up-on-any-events-you-missed">🎤 Catch up on any events you missed</h2>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXe8uUOI1BIxhPPJDffLkuRNhqY1lky8lUXg0GtLS0XT5UMjpEe8oXQTut8OujLMxkzKJY7Vs5JCt4Nil9LHGW1x8LAUgH5b4Ghsz4p7kOzG2jgiM6PImDCY8WqDDqeGGlKul-ZHAxUyVFBw6LfcBO9BBnDm?key=iJIW6hzxF9rCKOtohDTIQA" alt /></p>
<p>Did you miss our recent talks? Here are some highlights:</p>
<ul>
<li><p><a target="_blank" href="https://youtu.be/v11GCdJ5ELE?t=3">Build a Multichain RWA Lending Platform</a></p>
</li>
<li><p><a target="_blank" href="https://www.youtube.com/live/5loZw3iDOuo?si=-ZlXY3pv7YpWQUpA">Building a Multichain Tax Contract with ITS</a></p>
</li>
<li><p><a target="_blank" href="https://www.youtube.com/watch?v=P0FDD5n1CJo">Moralis Presents: Building Multichain Stablecoins</a></p>
</li>
</ul>
<p>We have a lot more planned for the upcoming months, so you don’t want to miss out. To stay up Follow us on <a target="_blank" href="https://x.com/axelarnetwork">X</a> and join <a target="_blank" href="https://discord.com/invite/aRZ3Ra6f7D">Discord</a> to stay abreast of upcoming developer content and live events.</p>
<p>We have a lot more planned for the upcoming months, so you don’t want to miss out. To stay up to date on the latest Axelar news, make sure you are <a target="_blank" href="https://blog.axelar.dev/newsletter">subscribed to the Axelar Devblog</a>.</p>
]]></content:encoded></item><item><title><![CDATA[🔥 Interchain Amplifier Testnet 🔥 Multichain Stablecoin, ERC-20 on Base & Optimism with ITS: July 2024 Dev Update 🏗️]]></title><description><![CDATA[Welcome to the June 2024 Axelar Developer Newsletter. You can subscribe to the Axelar Developer Newsletter to get direct updates.
Interchain Amplifier is Going Live on Testnet
Testing phase to begin Friday.

We're excited to share that the Interchain...]]></description><link>https://blog.axelar.dev/interchain-amplifier-testnet-multichain-stablecoin-erc-20-on-base-optimism-with-its-july-2024-dev-update</link><guid isPermaLink="true">https://blog.axelar.dev/interchain-amplifier-testnet-multichain-stablecoin-erc-20-on-base-optimism-with-its-july-2024-dev-update</guid><category><![CDATA[axelar]]></category><category><![CDATA[optimism]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[Developer]]></category><category><![CDATA[Stablecoins ]]></category><category><![CDATA[Smart Contracts]]></category><category><![CDATA[wasm]]></category><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Idris Olubisi]]></dc:creator><pubDate>Fri, 02 Aug 2024 15:10:40 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1722611382027/0ccb05a8-e5ea-43dc-b856-17b50e47ed43.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Welcome to the June 2024 Axelar Developer Newsletter. You can subscribe to the <a target="_blank" href="https://dashboard.mailerlite.com/forms/215012/103202424602232757/share"><strong>Axelar Developer Newsletter</strong></a> to get direct updates.</p>
<h2 id="heading-ihttpsdashboardmailerlitecomforms215012103202424602232757sharenterchain-amplifier-is-going-live-on-testnet"><a target="_blank" href="https://dashboard.mailerlite.com/forms/215012/103202424602232757/share">I</a>nterchain Amplifier is Going Live on Testnet</h2>
<p><em>Testing phase to begin Friday.</em></p>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXe9l4UojjgnnhmkezeCYsTS9-91SRERluqLAk8nIXbcTvztqYN1HES1kS-9MdjNGVq4LLlZo9XwILNOryJZc-fc7D_YXtv2jyL45LTu6OLXbeivYnVrV-JTI2hvceL7x0D3POL_Bww3dumKZFeJpC0nVAI?key=9XNuplkEyARSy7cpOYhHmQ" alt /></p>
<p>We're excited to share that the Interchain Amplifier is going live on Testnet today and will begin a test phase!</p>
<p>This marks a significant milestone in enhancing blockchain interoperability. Axelar’s Amplifier capabilities seamlessly connect a broad range of blockchain consensus engines and traditional off-chain systems with minimal developer overhead.</p>
<p>The core components of the <a target="_blank" href="https://docs.axelar.dev/dev/amplifier/introduction">Interchain Amplifier</a> on the Axelar network include:</p>
<ul>
<li><p>An on-chain message router</p>
</li>
<li><p>Gateways</p>
</li>
<li><p>CosmWasm methods for both receiving and sending messages</p>
</li>
</ul>
<p>Please note that the testnet is in the testing phase, and we will be onboarding new chains there in the coming weeks, so stay tuned.</p>
<p>Get started <a target="_blank" href="https://docs.axelar.dev/dev/amplifier/introduction">here</a> to check it out.</p>
<h2 id="heading-developer-content-highlights"><strong>Developer Content Highlights</strong></h2>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXczLmUnPYiyfli04ftQHICUGBJ6Y4Rlf2nJR9dTfPIIsamYilVzKW8QWYSDKauChjQPes6Ra-4s4Ps63GRMxuilL4SdJEKh4vIvDirL4Z1pyUjMrX3vRByukQX7clMAdqem8M1tasYTaL2iuTIZMNeHJhu8?key=9XNuplkEyARSy7cpOYhHmQ" alt /></p>
<p>We've just published several relevant technical articles and documentation updates.</p>
<h3 id="heading-its"><strong>ITS</strong></h3>
<ul>
<li><p><a target="_blank" href="https://blog.axelar.dev/building-multichain-stablecoins-part-one">Building Multichain Stablecoins Part One:</a> Deploy multichain stablecoins with Axelar's Interchain Token Service: custom ERC20 integrations, cross-chain transactions, and upgradable contracts.</p>
</li>
<li><p><a target="_blank" href="https://blog.axelar.dev/building-multichain-stablecoins-part-two">Building Multichain Stablecoins Part Two</a>: Deploy your stablecoin on a second chain, send a transaction between two chains with your token, and upgrade your token.</p>
</li>
<li><p><a target="_blank" href="https://moralis.io/how-to-mint-an-erc-20-token-on-base-with-the-interchain-token-service-in-5-steps/">How to Mint an ERC-20 Token on Base with the Interchain Token Service in 5 Steps:</a> This step-by-step guide will teach you how to mint a multichain ERC-20 token on the Base network using Axelar’s Interchain Token Service (ITS) and use the Moralis Token API to retrieve token balances easily.</p>
</li>
</ul>
<h3 id="heading-amplifier"><strong>Amplifier</strong></h3>
<ul>
<li><p><a target="_blank" href="https://docs.axelar.dev/dev/amplifier/chain-integration/governance-proposals">Governance Proposals for Integrating New EVM-based Chains</a>: Learn how to onboard a new chain with the Axelar Amplifier through governance proposals.</p>
</li>
<li><p><a target="_blank" href="https://docs.axelar.dev/dev/amplifier/add-rewards">Add rewards for Amplifier chain integrators</a>: Learn how to add funds to the rewards pool of an Amplifier-integrated chain.</p>
</li>
</ul>
<h3 id="heading-everything-else"><strong>Everything Else</strong></h3>
<ul>
<li><a target="_blank" href="https://blog.axelar.dev/how-to-fix-command-not-found-axelard-tofnd">How to fix <code>command not found: axelard</code> / <code>tofnd</code></a>: If you have followed the Axelar setup instructions for <a target="_blank" href="https://docs.axelar.dev/validator/amplifier/verifier-onboarding">becoming a verifier</a> but keep running into a command not found error when trying to run axelard or tofnd, try navigating to the folder your binary is in and referring directly to that binary instead of setting up an alias.</li>
</ul>
<h2 id="heading-developer-event-highlights"><strong>Developer Event Highlights</strong></h2>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXfoyi05hYb7xjRYZkaUPdVA0yzT3oe1MBAspQy_tKZG9WQ0gJuP496mrFfzcIWRqx801OLjvpIrKrArxKJkq06GIHIhWEaLvZaB5larU4m_xxM6Sknmpl_jyWTLzlRrBxbXgUQj-aXdODaFBzRPIEna1Mo?key=9XNuplkEyARSy7cpOYhHmQ" alt /></p>
<p>The Axelar team has been traveling the world to empower developers. Here are a few highlights from our talks:</p>
<ul>
<li><p><a target="_blank" href="https://www.youtube.com/watch?v=P0FDD5n1CJo">Moralis Presents: Building Multichain Stablecoins</a></p>
</li>
<li><p><a target="_blank" href="https://x.com/olanetsoft/status/1811353924172911022">OnHack Summer Buildathon, July 2024</a></p>
</li>
<li><p><a target="_blank" href="https://www.youtube.com/live/omaO6u4p8xA?si=XXXFh1fTfrekLTai">How to Build an Advanced ITS Token</a></p>
</li>
</ul>
<h3 id="heading-building-a-multichain-tax-contract-with-its">Building a Multichain Tax Contract with ITS</h3>
<p>Join us for a live workshop where we'll build a Multichain Tax Contract using the Interchain Token Service (ITS). Using the powerful Interchain Token Service (ITS), you'll learn how to create, deploy, and manage a custom token that operates across multiple networks. Watch as we implement smart contract logic that mints, burns, and applies fees to tokens as they travel between chains.</p>
<p>Set a reminder <a target="_blank" href="https://www.youtube.com/watch?v=5loZw3iDOuo">here</a>.</p>
<p>Follow us on <a target="_blank" href="https://x.com/axelarnetwork">X</a> and join <a target="_blank" href="https://discord.com/invite/aRZ3Ra6f7D">Discord</a> to stay abreast of upcoming developer content and live events.</p>
<p>We have a lot more planned for the upcoming months, so you don’t want to miss out. To stay up to date on the latest Axelar news, make sure you are <a target="_blank" href="https://blog.axelar.dev/newsletter">subscribed</a> to the Axelar Devblog.</p>
]]></content:encoded></item><item><title><![CDATA[Building Multichain Stablecoins: Part Two]]></title><description><![CDATA[Objective
In section one, you built an upgradable custom ERC20 stablecoin, that accrues value for token holders and burns a percentage of each token transfer to address token inflation. You also began building a factory contract that integrated with ...]]></description><link>https://blog.axelar.dev/building-multichain-stablecoins-part-two</link><guid isPermaLink="true">https://blog.axelar.dev/building-multichain-stablecoins-part-two</guid><category><![CDATA[axelar]]></category><category><![CDATA[Blockchain]]></category><category><![CDATA[Web3]]></category><category><![CDATA[Solidity]]></category><category><![CDATA[ERC20]]></category><category><![CDATA[Ethereum]]></category><category><![CDATA[Cryptocurrency]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[hardhat]]></category><category><![CDATA[ethers]]></category><dc:creator><![CDATA[Ben Weinberg]]></dc:creator><pubDate>Mon, 29 Jul 2024 18:45:57 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1722279418866/575082a7-3014-4ade-a525-44274fc9470c.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3 id="heading-objective">Objective</h3>
<p>In <a target="_blank" href="https://blog.axelar.dev/building-multichain-stablecoins-part-one">section one</a>, you built an upgradable custom ERC20 stablecoin, that accrues value for token holders and burns a percentage of each token transfer to address token inflation. You also began building a factory contract that integrated with Axelar's <a target="_blank" href="https://www.axelar.network/its">Interchain Token Service</a>. The factory deployed your custom ERC20 as an upgradable token using <a target="_blank" href="https://github.com/axelarnetwork/axelar-gmp-sdk-solidity/blob/main/contracts/deploy/Create3.sol">create3</a>. In this section, you will build out the functionality to deploy your token from your home chain onto a remote chain via your factory contract. You will also build out the functionality to upgrade your token to a simple V2 version. Finally, you will be able to test the token by actually sending a cross-chain transaction!</p>
<h3 id="heading-deploy-on-remote-chain">Deploy On Remote Chain</h3>
<p>Let's build out a separate function called <code>deployRemoteSemiNativeToken()</code> to handle this deployment. This function will be used to deploy an instance of the <code>SemiNativeToken</code> discussed earlier. Recall, Semi Native tokens will not have the transaction fee redistribution and burning functionality that Native tokens have, these will be simpler tokens merely to provide some pseudo presence for your stablecoin on a chain you may not want to operate your official token on yet.</p>
<p>Since there is no <code>burnRate</code> and <code>txFeeRate</code> needed here, all you need to pass into this function is the name of the destination chain you want to deploy your token on.</p>
<pre><code class="lang-solidity"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">deployRemoteSemiNativeToken</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> <span class="hljs-keyword">calldata</span> _destChain</span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title"><span class="hljs-keyword">payable</span></span> </span>{}
</code></pre>
<p>To start you will want to compute the <code>interchainTokenId</code> that ITS will use to register the token. To compute your token's <code>interchainTokenId</code> you need to hash the string <code>interchain-token-id</code> with the address that is deploying the token with a unique salt. This can be done as follows</p>
<pre><code class="lang-solidity"><span class="hljs-keyword">bytes32</span> computedTokenId <span class="hljs-operator">=</span> <span class="hljs-built_in">keccak256</span>(<span class="hljs-built_in">abi</span>.<span class="hljs-built_in">encode</span>(<span class="hljs-built_in">keccak256</span>(<span class="hljs-string">'its-interchain-token-id'</span>), <span class="hljs-keyword">address</span>(<span class="hljs-built_in">this</span>), S_SALT_ITS_TOKEN));
</code></pre>
<p>Next, you will need to construct and send your <a target="_blank" href="https://docs.axelar.dev/dev/general-message-passing/overview#at-the-source-chain">GMP message</a> to the destination chain.</p>
<p>Your GMP message needs to be of type <code>bytes</code> so let's encode the different components of your GMP message in a <code>bytes</code> type object. The three unique messages you will be encoding here a first your <code>computedTokenId</code>, second the Semi Native Token's <code>creationCode</code>, and last the Semi Native Token's <code>selector</code>. This can be done as follows</p>
<pre><code class="lang-solidity"><span class="hljs-keyword">bytes</span> <span class="hljs-keyword">memory</span> gmpPayload <span class="hljs-operator">=</span> <span class="hljs-built_in">abi</span>.<span class="hljs-built_in">encode</span>(computedTokenId, <span class="hljs-keyword">type</span>(SemiNativeToken).<span class="hljs-built_in">creationCode</span>, SemiNativeToken.initialize.<span class="hljs-built_in">selector</span>);
</code></pre>
<p>Now that you have your encoded message you can interact with the Axelar <code>GasService</code> and <code>Gateway</code> to send your GMP message. If this is new to you, feel free to <a target="_blank" href="https://www.youtube.com/watch?v=htMVIYzGA34&amp;t=1s">watch this tutorial</a> for the basics of sending a GMP message.</p>
<p>To pay for the transaction with the <a target="_blank" href="https://github.com/axelarnetwork/axelar-cgp-solidity/blob/main/contracts/gas-service/AxelarGasService.sol">Axelar Gas Service</a> you must call the <code>payNativeGasForContractCall()</code> function. This function requires the address making the payment, the destination chain, the destination address, the gmp message, and the refund address (in the event of an overly high gas payment) as its parameters.</p>
<p>This can be written out as follows:</p>
<pre><code class="lang-solidity">   s_gasService.payNativeGasForContractCall{ <span class="hljs-built_in">value</span>: <span class="hljs-built_in">msg</span>.<span class="hljs-built_in">value</span> }(
            <span class="hljs-keyword">address</span>(<span class="hljs-built_in">this</span>),
            _destChain,
            <span class="hljs-keyword">address</span>(s_deployer).toString(),
            gmpPayload,
            <span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>
        );
</code></pre>
<p>Note the <code>s_deployer</code> variable that is referenced as the destination address. This is pointing to a storage variable called <code>s_deployer</code> that has yet to be defined.</p>
<p>It can be defined up top with the rest of your storage variable and passed in as the fifth parameter to your <code>initialize</code> function so that your <code>initialize</code> function now looks like this.</p>
<pre><code class="lang-bash">   <span class="hljs-keyword">function</span> initialize(
        IInterchainTokenService _its,
        IAxelarGasService _gasService,
        IAxelarGateway _gateway,
        AccessControl _accessControl,
        Deployer _deployer
    ) external initializer {
        s_its = _its;
        s_gasService = _gasService;
        s_gateway = _gateway;
        s_accessControl = _accessControl;
        s_deployer = _deployer;

        S_SALT_ITS_TOKEN = 0x0000000000000000000000000000000000000000000000000000000000003039; //12345
    }
</code></pre>
<p>Now that your <code>s_deployer</code> function is available you can send your GMP message to the destination chain you need to call the <code>callContract()</code> function on the <a target="_blank" href="https://github.com/axelarnetwork/axelar-cgp-solidity/blob/main/contracts/AxelarGateway.sol">Axelar Gateway</a> contract. It requires similar parameters to the previous function, namely the destination chain, destination address, and GMP message.</p>
<pre><code class="lang-solidity">s_gateway.callContract(_destChain, <span class="hljs-keyword">address</span>(s_deployer).toString(), gmpPayload);
</code></pre>
<p>Your <code>deployRemoteSemiNativeToken()</code> should now be complete. Note the conditional that was added at the beginning of the function that references a new mapping you need to add in storage called <code>s_semiNativeTokens</code>, this will be where you register all your remote <code>SemiNativeTokens</code> that you want your factory contract to be aware of. In this <code>if</code> statement, you are making sure that the <code>SemiNativeToken</code> has not yet been deployed on the remote chain you're attempting to deploy to.</p>
<pre><code class="lang-solidity">    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">deployRemoteSemiNativeToken</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> <span class="hljs-keyword">calldata</span> _destChain</span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title"><span class="hljs-keyword">payable</span></span> </span>{
        <span class="hljs-keyword">if</span> (s_semiNativeTokens[_destChain] <span class="hljs-operator">!</span><span class="hljs-operator">=</span> <span class="hljs-keyword">address</span>(<span class="hljs-number">0</span>) <span class="hljs-operator">&amp;</span><span class="hljs-operator">&amp;</span> s_nativeToken <span class="hljs-operator">!</span><span class="hljs-operator">=</span> <span class="hljs-keyword">address</span>(<span class="hljs-number">0</span>)) <span class="hljs-keyword">revert</span> TokenAlreadyDeployed();

        <span class="hljs-keyword">bytes32</span> computedTokenId <span class="hljs-operator">=</span> <span class="hljs-built_in">keccak256</span>(<span class="hljs-built_in">abi</span>.<span class="hljs-built_in">encode</span>(<span class="hljs-built_in">keccak256</span>(<span class="hljs-string">'its-interchain-token-id'</span>), <span class="hljs-keyword">address</span>(<span class="hljs-built_in">this</span>), S_SALT_ITS_TOKEN));

        <span class="hljs-keyword">bytes</span> <span class="hljs-keyword">memory</span> gmpPayload <span class="hljs-operator">=</span> <span class="hljs-built_in">abi</span>.<span class="hljs-built_in">encode</span>(computedTokenId, <span class="hljs-keyword">type</span>(SemiNativeToken).<span class="hljs-built_in">creationCode</span>, SemiNativeToken.initialize.<span class="hljs-built_in">selector</span>);

        s_gasService.payNativeGasForContractCall{ <span class="hljs-built_in">value</span>: <span class="hljs-built_in">msg</span>.<span class="hljs-built_in">value</span> }(
            <span class="hljs-keyword">address</span>(<span class="hljs-built_in">this</span>),
            _destChain,
            <span class="hljs-keyword">address</span>(s_deployer).toString(),
            gmpPayload,
            <span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>
        );

        s_gateway.callContract(_destChain, <span class="hljs-keyword">address</span>(s_deployer).toString(), gmpPayload);
    }
</code></pre>
<p>Now that the transaction has been sent from the contract on the source chain. It needs to be received on the destination chain.</p>
<h3 id="heading-deployer-contract">Deployer Contract</h3>
<p>Your factory contract is now complete! However, you need to have a factory on all the destination chains that your factory will interact with. To make the factory more modular you can break up the following logic that still needs to be built out into a separate contract that you can call <em>Deployer.</em></p>
<p>This will also be an upgradable contract with a similar <code>initialize()</code> function to the factory.</p>
<pre><code class="lang-solidity"><span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">Deployer</span> </span>{
   IInterchainTokenService <span class="hljs-keyword">public</span> s_its;
   AccessControl <span class="hljs-keyword">public</span> s_accessControl;
   IAxelarGateway <span class="hljs-keyword">public</span> s_gateway;

   <span class="hljs-keyword">bytes32</span> <span class="hljs-keyword">public</span> S_SALT_ITS_TOKEN;

   <span class="hljs-comment">/// @custom:oz-upgrades-unsafe-allow constructor</span>
   <span class="hljs-function"><span class="hljs-keyword">constructor</span>(<span class="hljs-params"></span>) </span>{
       _disableInitializers();
   }
  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">initialize</span>(<span class="hljs-params">IInterchainTokenService _its, AccessControl _accessControl, IAxelarGateway _gateway</span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title">initializer</span> </span>{
        s_its <span class="hljs-operator">=</span> _its;
        s_accessControl <span class="hljs-operator">=</span> _accessControl;
        s_gateway <span class="hljs-operator">=</span> _gateway;

        S_SALT_ITS_TOKEN <span class="hljs-operator">=</span> <span class="hljs-number">0x0000000000000000000000000000000000000000000000000000000000003039</span>; <span class="hljs-comment">//12345</span>
    }
}
</code></pre>
<p>Notice the <code>S_SALT_ITS_TOKEN</code> is the exact same value as the <code>S_SALT_ITS_TOKEN</code> in the in the <code>TokenFactory</code> contract. This is to ensure that the ITS token that will be wired up here on the destination chain will map to the same <code>interchainTokenId</code>.</p>
<h4 id="heading-execute">Execute</h4>
<p>Recall where you left off in the <code>TokenFactory</code> contract. You were able to send a cross-chain message from the source chain via the <code>deployRemoteSemiNativeToken()</code> function. Now, to handle that message on the destination chain you can use the <code>execute()</code> function.</p>
<p>This function takes several parameters including the <code>_commandId</code>, <code>_sourceChain</code>, <code>_sourceAddress</code>, and <code>_payload</code>. The <code>payload</code> is the GMP message you sent from the source chain</p>
<pre><code class="lang-solidity"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">execute</span>(<span class="hljs-params"><span class="hljs-keyword">bytes32</span> _commandId, <span class="hljs-keyword">string</span> <span class="hljs-keyword">calldata</span> _sourceChain, <span class="hljs-keyword">string</span> <span class="hljs-keyword">calldata</span> _sourceAddress, <span class="hljs-keyword">bytes</span> <span class="hljs-keyword">calldata</span> _payload</span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> </span>{}
</code></pre>
<p>The first line that must be written here is a call via the <code>AxelarGateway</code> to <code>validateContractCall()</code>. This function will ensure that the <code>payload</code> being passed in is a message that has been validated and confirmed by the Axelar validator set rather than an invalid message from a potentially malicious caller. This can be called as follows</p>
<pre><code class="lang-solidity"><span class="hljs-keyword">if</span> (<span class="hljs-operator">!</span>s_gateway.validateContractCall(_commandId, _sourceChain, _sourceAddress, <span class="hljs-built_in">keccak256</span>(_payload))) <span class="hljs-keyword">revert</span> NotApprovedByGateway();
</code></pre>
<p>Now that you know the <code>payload</code> is valid you can decode it to get the actual GMP message you passed in from the source chain. Recall, in the <code>TokenFactory</code> contract on the src chain encoded a computed <code>tokenId</code> value, the creation code of the <code>SemiNativeToken</code> contract, and the <code>selector</code> for the <code>SemiNativeToken</code> contract. These values can be decoded using the <code>abi.decode()</code> function</p>
<pre><code class="lang-solidity">(<span class="hljs-keyword">bytes32</span> computedTokenId, <span class="hljs-keyword">bytes</span> <span class="hljs-keyword">memory</span> semiNativeTokenBytecode, <span class="hljs-keyword">bytes4</span> semiNativeSelector) <span class="hljs-operator">=</span> <span class="hljs-built_in">abi</span>.<span class="hljs-built_in">decode</span>(
    _payload,
    (<span class="hljs-keyword">bytes32</span>, <span class="hljs-keyword">bytes</span>, <span class="hljs-keyword">bytes4</span>)
);
</code></pre>
<p>With your data now available on the destination chain you can deploy the <code>SemiNativeToken</code> just like you deployed the origin <code>NativeToken</code> on the source chain.</p>
<p>Since the <code>SemiNativeToken</code> will also be an upgradable token you must deploy the <code>implementation</code> first followed by the <code>proxy</code> that will point to the <code>implementation</code>. Note the salt value being passed into <code>_create3()</code> here is the same value in the <code>deployHomeNative()</code> function, meaning that the implementation address of these tokens will be the same address.</p>
<pre><code class="lang-solidity"><span class="hljs-keyword">address</span> newTokenImpl <span class="hljs-operator">=</span> _create3(semiNativeTokenBytecode, <span class="hljs-number">0x00000000000000000000000000000000000000000000000000000000000004D2</span>);
<span class="hljs-keyword">if</span> (newTokenImpl <span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-keyword">address</span>(<span class="hljs-number">0</span>)) <span class="hljs-keyword">revert</span> DeploymentFailed();
</code></pre>
<p>Next, you can call the <code>getEncodedCreationCodeSemiNative()</code> code, this will be very similar to the <code>getEncodedCreationCodeNative()</code> you wrote in the <code>TokenFactory</code> contract.</p>
<pre><code class="lang-solidity">    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">_getEncodedCreationCodeSemiNative</span>(<span class="hljs-params">
        <span class="hljs-keyword">address</span> _proxyAdmin,
        <span class="hljs-keyword">address</span> _implAddr,
        <span class="hljs-keyword">bytes32</span> _itsTokenId,
        <span class="hljs-keyword">bytes4</span> semiNativeSelector
    </span>) <span class="hljs-title"><span class="hljs-keyword">internal</span></span> <span class="hljs-title"><span class="hljs-keyword">view</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">bytes</span> <span class="hljs-keyword">memory</span> proxyCreationCode</span>) </span>{
        <span class="hljs-comment">//init func args</span>
        <span class="hljs-keyword">bytes</span> <span class="hljs-keyword">memory</span> initData <span class="hljs-operator">=</span> <span class="hljs-built_in">abi</span>.<span class="hljs-built_in">encodeWithSelector</span>(semiNativeSelector, s_its, _itsTokenId);

        <span class="hljs-comment">//concat bytecode + init func args</span>
        proxyCreationCode <span class="hljs-operator">=</span> <span class="hljs-built_in">abi</span>.<span class="hljs-built_in">encodePacked</span>(<span class="hljs-keyword">type</span>(TransparentUpgradeableProxy).<span class="hljs-built_in">creationCode</span>, <span class="hljs-built_in">abi</span>.<span class="hljs-built_in">encode</span>(_implAddr, _proxyAdmin, initData));
    }
</code></pre>
<p>Now back in your <code>execute()</code> function you can call the <code>_getEncodedCreationCodeSemiNative()</code>. The output of this will be your <code>proxy</code> contract's creation code</p>
<pre><code class="lang-solidity">   <span class="hljs-keyword">bytes</span> <span class="hljs-keyword">memory</span> creationCodeProxy <span class="hljs-operator">=</span> _getEncodedCreationCodeSemiNative(
            <span class="hljs-keyword">address</span>(<span class="hljs-built_in">this</span>),
            newTokenImpl,
            computedTokenId,
            semiNativeSelector
        );
</code></pre>
<p>You can now deploy your <code>proxy</code> contract and store its address.</p>
<pre><code class="lang-solidity"><span class="hljs-keyword">address</span> newTokenProxy <span class="hljs-operator">=</span> _create3(creationCodeProxy, <span class="hljs-number">0x000000000000000000000000000000000000000000000000000000000000007B</span>);
<span class="hljs-keyword">if</span> (newTokenProxy <span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-keyword">address</span>(<span class="hljs-number">0</span>)) <span class="hljs-keyword">revert</span> DeploymentFailed();
s_tokenProxy <span class="hljs-operator">=</span> ITransparentUpgradeableProxy(newTokenProxy);
</code></pre>
<p>The final thing you need to do is connect your newly deployed token to ITS. You can do this exactly as you did before, by calling the <code>deployTokenManager()</code>.</p>
<pre><code class="lang-solidity">  s_its.deployTokenManager(
            S_SALT_ITS_TOKEN,
            <span class="hljs-string">''</span>,
            ITokenManagerType.TokenManagerType.MINT_BURN,
            <span class="hljs-built_in">abi</span>.<span class="hljs-built_in">encode</span>(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>.toBytes(), newTokenProxy),
            <span class="hljs-number">0</span>
        );
</code></pre>
<p>Note, that the parameters passed in are exactly the same as in the <code>TokenFactory</code> contract, the only difference is the <code>TokenManagerType</code>. Rather than passing in a lock/unlock token manager, you can pass a mint/burn, the reason being that this execution is taking place on a remote chain rather than the source chain where you want to lock up bridged tokens.</p>
<p>Your completed <code>execute()</code> function should be as follows</p>
<pre><code class="lang-solidity">
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">execute</span>(<span class="hljs-params"><span class="hljs-keyword">bytes32</span> _commandId, <span class="hljs-keyword">string</span> <span class="hljs-keyword">calldata</span> _sourceChain, <span class="hljs-keyword">string</span> <span class="hljs-keyword">calldata</span> _sourceAddress, <span class="hljs-keyword">bytes</span> <span class="hljs-keyword">calldata</span> _payload</span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> </span>{
        <span class="hljs-keyword">if</span> (<span class="hljs-operator">!</span>s_gateway.validateContractCall(_commandId, _sourceChain, _sourceAddress, <span class="hljs-built_in">keccak256</span>(_payload))) <span class="hljs-keyword">revert</span> NotApprovedByGateway();

        (<span class="hljs-keyword">bytes32</span> computedTokenId, <span class="hljs-keyword">bytes</span> <span class="hljs-keyword">memory</span> semiNativeTokenBytecode, <span class="hljs-keyword">bytes4</span> semiNativeSelector) <span class="hljs-operator">=</span> <span class="hljs-built_in">abi</span>.<span class="hljs-built_in">decode</span>(
            _payload,
            (<span class="hljs-keyword">bytes32</span>, <span class="hljs-keyword">bytes</span>, <span class="hljs-keyword">bytes4</span>)
        );

        <span class="hljs-keyword">address</span> newTokenImpl <span class="hljs-operator">=</span> _create3(semiNativeTokenBytecode, <span class="hljs-number">0x00000000000000000000000000000000000000000000000000000000000004D2</span>);
        <span class="hljs-keyword">if</span> (newTokenImpl <span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-keyword">address</span>(<span class="hljs-number">0</span>)) <span class="hljs-keyword">revert</span> DeploymentFailed();

        <span class="hljs-keyword">bytes</span> <span class="hljs-keyword">memory</span> creationCodeProxy <span class="hljs-operator">=</span> _getEncodedCreationCodeSemiNative(
            <span class="hljs-keyword">address</span>(<span class="hljs-built_in">this</span>),
            newTokenImpl,
            computedTokenId,
            semiNativeSelector
        );

        <span class="hljs-keyword">address</span> newTokenProxy <span class="hljs-operator">=</span> _create3(creationCodeProxy, <span class="hljs-number">0x000000000000000000000000000000000000000000000000000000000000007B</span>);
        <span class="hljs-keyword">if</span> (newTokenProxy <span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-keyword">address</span>(<span class="hljs-number">0</span>)) <span class="hljs-keyword">revert</span> DeploymentFailed();

        s_tokenProxy <span class="hljs-operator">=</span> ITransparentUpgradeableProxy(newTokenProxy);

        <span class="hljs-comment">// Deploy ITS</span>
        s_its.deployTokenManager(
            S_SALT_ITS_TOKEN,
            <span class="hljs-string">''</span>,
            ITokenManagerType.TokenManagerType.MINT_BURN,
            <span class="hljs-built_in">abi</span>.<span class="hljs-built_in">encode</span>(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>.toBytes(), newTokenProxy),
            <span class="hljs-number">0</span>
        );
    }
</code></pre>
<h4 id="heading-optional-callback">Optional Callback</h4>
<p>Axelar allows for <a target="_blank" href="https://www.youtube.com/watch?v=SjVJotyyAPg&amp;t=1s">two-way callback functions</a> to have an immediate transaction back from the destination chain to the source chain. In this case you can send the address of your newly deployed <code>SemiNativeToken</code> proxy back to your source chain's <code>TokenFactory</code> contract.</p>
<p>This can be done very easily in your <code>execute()</code> function in the <code>Deployer</code> contract. Right underneath where you called <code>deployTokenManager()</code> you can call the <code>callContract()</code> function.</p>
<pre><code class="lang-solidity">s_gateway.callContract(_sourceChain, _sourceAddress, <span class="hljs-built_in">abi</span>.<span class="hljs-built_in">encode</span>(newTokenProxy));
</code></pre>
<p>This call will make a cross-chain transaction back to the source chain to the source address that sends the original transaction. You can encode the address of the newTokenProxy as the GMP message to be sent back to the <code>TokenFactory</code> contract.</p>
<p>Now back on the <code>TokenFactory</code> contract you will need to implement and <code>execute()</code> method just like you did on the <code>Deployer</code> contract to handle the incoming GMP message.</p>
<p>In this <code>execute</code> function you will of course need to implement the <code>validateContractCall()</code> function again and then you can decode the GMP message and store in the TokenFactory contract.</p>
<pre><code class="lang-solidity">  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">execute</span>(<span class="hljs-params"><span class="hljs-keyword">bytes32</span> _commandId, <span class="hljs-keyword">string</span> <span class="hljs-keyword">calldata</span> _sourceChain, <span class="hljs-keyword">string</span> <span class="hljs-keyword">calldata</span> _sourceAddress, <span class="hljs-keyword">bytes</span> <span class="hljs-keyword">calldata</span> _payload</span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> </span>{
        <span class="hljs-keyword">if</span> (<span class="hljs-operator">!</span>s_gateway.validateContractCall(_commandId, _sourceChain, _sourceAddress, <span class="hljs-built_in">keccak256</span>(_payload))) <span class="hljs-keyword">revert</span> NotApprovedByGateway();
        s_semiNativeTokens[_sourceChain] <span class="hljs-operator">=</span> <span class="hljs-built_in">abi</span>.<span class="hljs-built_in">decode</span>(_payload, (<span class="hljs-keyword">address</span>));
    }
</code></pre>
<h3 id="heading-upgrade-seminativetoken">Upgrade <code>SemiNativeToken</code></h3>
<p>The final bit of functionality for this demo is the ability to upgrade your token directly from the <code>Deployer</code> contract. In the event that you choose to upgrade your <code>SemiNativeToken</code>.</p>
<p>To upgrade your token's proxy you will need to trigger the <code>upgradeAndCall()</code> function from your <code>Proxy Admin</code> contract. In your <code>Deployer</code> function create a new function called <code>upgradeSemiNativeToken()</code></p>
<pre><code class="lang-solidity"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">upgradeSemiNativeToken</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> _proxyAdmin</span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title">onlyAdmin</span> </span>{}
</code></pre>
<p>First, you need to deploy a new <code>implementation</code> contract for your <code>proxy</code> to point to. For the purpose of this demo you can simply deploy a new <code>SemiNativeTokenV2</code> contract with the exact same code and add a new function to it called <code>isV2()</code> that returns a <code>bool</code> .</p>
<pre><code class="lang-solidity">   <span class="hljs-keyword">address</span> newTokenImpl <span class="hljs-operator">=</span> _create3(
            <span class="hljs-keyword">type</span>(SemiNativeTokenV2).<span class="hljs-built_in">creationCode</span>,
            <span class="hljs-number">0x0000000000000000000000000000000000000000000000000000000000003439</span>
        );
        <span class="hljs-keyword">if</span> (newTokenImpl <span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-keyword">address</span>(<span class="hljs-number">0</span>)) <span class="hljs-keyword">revert</span> DeploymentFailed();
</code></pre>
<p>Now with your <code>upgradeAndCall()</code> function deployed, you can upgrade the token <code>proxy</code> to the <code>newTokenImpl</code> that you just deployed.</p>
<pre><code class="lang-solidity">ProxyAdmin(_proxyAdmin).upgradeAndCall(s_tokenProxy, newTokenImpl, <span class="hljs-string">''</span>);
</code></pre>
<p>At this point, your proxy should successfully be pointing to a new implementation address!</p>
<h3 id="heading-deploy">Deploy</h3>
<p>It is critical for the <code>_create3()</code> addresses written out in the <code>Factory</code> and <code>Deployer</code> contracts to work correctly that these contracts are also the same address otherwise the contracts they deploy will be different from one another. To deploy these contracts you can use Axelar's <code>create3Deployer</code> script from Axelar's <a target="_blank" href="https://github.com/axelarnetwork/axelar-gmp-sdk-solidity">gmp-sdk</a> package.</p>
<p>You can deploy the contract via <a target="_blank" href="https://hardhat.org/hardhat-runner/docs/advanced/create-task">Hardhat Tasks</a>. Let's start with Moonbase.</p>
<h4 id="heading-moonbase">Moonbase</h4>
<p>Define your task like this</p>
<pre><code class="lang-javascript">task(<span class="hljs-string">'deployMoonbase'</span>, <span class="hljs-string">'deploy deployer on remote chain (Moonbase for testing'</span>).setAction(<span class="hljs-keyword">async</span> (taskArgs, hre) =&gt; {}
</code></pre>
<p>Now in the task you can deploy the contract for Moonbase.</p>
<p>First, you need to call the <code>getWallet()</code> function, which is written up in the <code>utils</code> folder. This will get your live wallet for the Moonbase chain. Make sure to include your private key in the <code>.env</code> file for the wallet to work correctly.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> wallet = getWallet(chains[<span class="hljs-number">1</span>].rpc, hre);
</code></pre>
<p>Now you can deploy your upgradable <code>AccessControl</code> and <code>Deployer</code> contract on Moonbase. To do this simply call the <code>create3DeployContract()</code> from the <code>Create3Deployer</code> script.</p>
<pre><code class="lang-javascript">    <span class="hljs-keyword">const</span> implAccessControl = <span class="hljs-keyword">await</span> create3DeployContract(create3DeployerAddress, wallet, AccessControl, <span class="hljs-number">1720</span>, []);
    <span class="hljs-keyword">const</span> implDeployer = <span class="hljs-keyword">await</span> create3DeployContract(create3DeployerAddress, wallet, Deployer, <span class="hljs-number">1721</span>, []);

    <span class="hljs-keyword">const</span> proxyAccess = <span class="hljs-keyword">await</span> create3DeployContract(create3DeployerAddress, wallet, <span class="hljs-built_in">Proxy</span>, <span class="hljs-number">1722</span>, [
        implAccessControl.address,
        wallet.address,
        <span class="hljs-string">'0x'</span>,
    ]);
    <span class="hljs-keyword">const</span> proxyDeployer = <span class="hljs-keyword">await</span> create3DeployContract(create3DeployerAddress, wallet, <span class="hljs-built_in">Proxy</span>, <span class="hljs-number">1723</span>, [
        implDeployer.address,
        wallet.address,
        <span class="hljs-string">'0x'</span>,
    ]);

    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`proxyAccess <span class="hljs-subst">${proxyAccess.address}</span>`</span>);
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`proxyDeployer <span class="hljs-subst">${proxyDeployer.address}</span>`</span>);
</code></pre>
<p>Once deployed you can <code>initialize</code> your two newly deployed contracts.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> AccessControlFactory = <span class="hljs-keyword">await</span> ethers.getContractFactory(<span class="hljs-string">'AccessControl'</span>);
<span class="hljs-keyword">const</span> DeployerFactory = <span class="hljs-keyword">await</span> ethers.getContractFactory(<span class="hljs-string">'Deployer'</span>);

<span class="hljs-keyword">const</span> proxyAccessControlInstance = <span class="hljs-keyword">await</span> AccessControlFactory.attach(proxyAccess.address);
<span class="hljs-keyword">const</span> proxyDeployerInstance = <span class="hljs-keyword">await</span> DeployerFactory.attach(proxyDeployer.address);

<span class="hljs-keyword">await</span> proxyAccessControlInstance.initialize(wallet.address);
<span class="hljs-keyword">await</span> proxyDeployerInstance.initialize(chains[<span class="hljs-number">1</span>].its, proxyAccess.address, chains[<span class="hljs-number">1</span>].gateway);
</code></pre>
<p>To trigger this hardhat script in your CLI type</p>
<p><code>hh deployMoonbase --network moonbase</code></p>
<h4 id="heading-celo">Celo</h4>
<p>The same task can be set for the <code>Celo</code> deployment. The one difference is that this time you will need to pass in the address of the <code>deployer</code> that you <code>TokenFactory</code> will be interacting with.</p>
<p>This can be done with the <code>addParam</code> call.</p>
<pre><code class="lang-javascript">task(<span class="hljs-string">'deployHomeCelo'</span>, <span class="hljs-string">'deploy factory on home chain, (celo for testing)'</span>)
    .addParam(<span class="hljs-string">'deployer'</span>, <span class="hljs-string">'Deployer on dest chain'</span>)
    .setAction(<span class="hljs-keyword">async</span> (taskArgs, hre) =&gt; {
        <span class="hljs-keyword">const</span> wallet = getWallet(chains[<span class="hljs-number">0</span>].rpc, hre);

        <span class="hljs-keyword">const</span> implAccessControl = <span class="hljs-keyword">await</span> create3DeployContract(create3DeployerAddress, wallet, AccessControl, <span class="hljs-number">1720</span>, []);
        <span class="hljs-keyword">const</span> implFactory = <span class="hljs-keyword">await</span> create3DeployContract(create3DeployerAddress, wallet, Factory, <span class="hljs-number">1721</span>, []);

        <span class="hljs-keyword">const</span> proxyAccess = <span class="hljs-keyword">await</span> create3DeployContract(create3DeployerAddress, wallet, <span class="hljs-built_in">Proxy</span>, <span class="hljs-number">1722</span>, [
            implAccessControl.address,
            wallet.address,
            <span class="hljs-string">'0x'</span>,
        ]);

        <span class="hljs-keyword">const</span> proxyFactory = <span class="hljs-keyword">await</span> create3DeployContract(create3DeployerAddress, wallet, <span class="hljs-built_in">Proxy</span>, <span class="hljs-number">1723</span>, [
            implFactory.address,
            wallet.address,
            <span class="hljs-string">'0x'</span>,
        ]);

        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`celo contract address: <span class="hljs-subst">${proxyFactory.address}</span>`</span>);

        <span class="hljs-keyword">const</span> AccessControlFactory = <span class="hljs-keyword">await</span> ethers.getContractFactory(<span class="hljs-string">'AccessControl'</span>);
        <span class="hljs-keyword">const</span> TokenFactoryFactory = <span class="hljs-keyword">await</span> ethers.getContractFactory(<span class="hljs-string">'TokenFactory'</span>);

        <span class="hljs-keyword">const</span> proxyAccessControlInstance = <span class="hljs-keyword">await</span> AccessControlFactory.attach(proxyAccess.address);
        <span class="hljs-keyword">const</span> proxyFactoryInstance = <span class="hljs-keyword">await</span> TokenFactoryFactory.attach(proxyFactory.address);

        <span class="hljs-keyword">await</span> proxyAccessControlInstance.initialize(wallet.address);

        <span class="hljs-keyword">await</span> proxyFactoryInstance.initialize(
            chains[<span class="hljs-number">0</span>].its,
            chains[<span class="hljs-number">0</span>].gasService,
            chains[<span class="hljs-number">0</span>].gateway,
            proxyAccess.address,
            taskArgs.deployer,
        );
    });
</code></pre>
<p>Great! At this point once you run <code>hh deployHomeCelo --deployer "&lt;YOUR_DEPLOYER_ADDRESS&gt;" --network celo</code> you should get your home chain's <code>TokenFactory</code> address in the cli.</p>
<h3 id="heading-test">Test</h3>
<p>Let's now test this contract using the <code>hardhat cli</code></p>
<p>To wire up your contract to your cli you type in</p>
<pre><code class="lang-bash">hh console --network &lt;YOUR_HOME_CHAIN&gt;

const Contract = await ethers.getContractFactory(<span class="hljs-string">"TokenFactory"</span>)
const contract = await Contract.attach(<span class="hljs-string">"&lt;YOUR_CONTRACT_ADDRESS&gt;"</span>)
</code></pre>
<p>Now with your contract connected to the cli, let's use your newly deployed <code>TokenFactory</code> on the home chain to deploy a <code>NativeToken</code> on your home chain. You can do this by calling the <code>deployHomeNative()</code> function.</p>
<pre><code class="lang-bash">await contract.deployHomeNative()
</code></pre>
<p>this should return a transaction receipt in your CLI and store the deployed instance of your contract in the <code>s_tokenProxy</code> storage variable. Query the variable to make sure you have the address stored correctly.</p>
<pre><code class="lang-bash">await contract.s_tokenProxy()
--&gt; &lt;<span class="hljs-string">"YOUR_TOKEN_ADDRESS"</span>&gt; //should be returned
</code></pre>
<p>Now with your token deployed on the home chain you can call the <code>deployRemoteSemiNativeToken()</code> on the remote chain.</p>
<pre><code class="lang-bash">await contract.deployRemoteSemiNativeToken(<span class="hljs-string">"moonbeam"</span>, {value: <span class="hljs-string">"1000000000000000000"</span>})
</code></pre>
<p>This should return a transaction hash that you can view on the <a target="_blank" href="https://testnet.axelarscan.io/">Axelarscan Block Explorer</a>. While this cross-chain transaction is executing you can interact with your token on the home chain to <code>mint</code> some new tokens to your contract.</p>
<p>You can wire it up similarly to how you wired up the <code>TokenFactory</code> contract.</p>
<pre><code class="lang-bash">const Contract = await ethers.getContractFactory(<span class="hljs-string">"NativeToken"</span>)
const contract = await Contract.attach(<span class="hljs-string">"&lt;YOUR_TOKEN_ADDRESS"</span>)
</code></pre>
<p>Now with your token wired up you can mint tokens to your account that you will transfer to the destination chain.</p>
<pre><code class="lang-bash">await contract.mint(<span class="hljs-string">"YOUR_RECEIVING_ADDRESS"</span>, 1000000000000000000)
</code></pre>
<p>You may need to specify a <code>gasLimit</code> when running the previous transaction.</p>
<p>At this point you should have a balance of your new token in your wallet equal to what you just minted. You can now transfer this token between accounts to make sure that the <code>burn</code> and <code>txFee</code> deductions are working correctly.</p>
<h4 id="heading-cross-chain-transfer">Cross Chain Transfer</h4>
<p>With your token now deployed on multiple chains and a balance minted on the home chain you can now transfer your token from the home chain to the remote chain.</p>
<p>If you set a lock/unlock transaction token manager on the home chain then you will need to <code>approve</code> the Interchain Token Service (ITS) contract to handle the tokens on your behalf. This is because <a target="_blank" href="https://github.com/axelarnetwork/interchain-token-service/blob/main/contracts/TokenHandler.sol#L109C13-L109C31">ITS will call</a> the <code>transferFrom()</code> function when sending the cross chain transaction.</p>
<pre><code class="lang-bash">await contract.approve(<span class="hljs-string">"0xB5FB4BE02232B1bBA4dC8f81dc24C26980dE9e3C"</span>, 1000000000000000000)
</code></pre>
<p>You can now interact with ITS programmatically to trigger the cross-chain transfer or you can go through the <a target="_blank" href="https://alfajores.celoscan.io/address/0xB5FB4BE02232B1bBA4dC8f81dc24C26980dE9e3C#writeProxyContract">explorer</a>.</p>
<p>To send the transfer from the home chain to the remote chain you will need to call the <code>interchainTransfer()</code> function on the ITS contract.</p>
<p>The following params are required</p>
<ol>
<li><p><code>payableAmount</code>: The gas amount to be paid for the cross-chain tx</p>
</li>
<li><p><code>tokenId</code>: The interchain token id of your token. You can find your <code>tokenId</code> in the logs of <code>NativeTokenDeployed()</code> event</p>
</li>
<li><p><code>destinationChain</code>: The chain where your <code>Deployer</code> contract was deployed to</p>
</li>
<li><p><code>destinationAddress</code>: The address you want to receive the tokens on the destination chain</p>
</li>
<li><p><code>amount</code>: Amount of tokens to be sent</p>
</li>
<li><p><code>metadata</code>: Data to be sent with your token. You can leave this as <code>0x</code> for this example</p>
</li>
<li><p><code>gasValue</code>: The gas amount to be paid for the cross-chain tx (in <code>wei</code> this time)</p>
</li>
</ol>
<p>This should trigger another cross-chain transaction that you can track on Axelarscan.</p>
<p>Once this transaction has executed you should now see your balance increment on the destination chain!</p>
<h4 id="heading-upgrade">Upgrade</h4>
<p>To upgrade the token you can call the <code>upgradeSemiNativeToken()</code> function your deployer</p>
<pre><code class="lang-bash">await contract.upgradeSemiNativeToken(<span class="hljs-string">"&lt;YOUR_PROXY_ADMIN_ADDRESS&gt;"</span>)
</code></pre>
<p>Once this is executed. You can query the <code>isV2()</code> token function at the same deployed token proxy address at the destination chain, which should now be returning <code>true</code></p>
<pre><code class="lang-bash">const Contract = await ethers.getContractFactory(<span class="hljs-string">"SemiNativeTokenV2"</span>)
const contract = await Contract.attach(<span class="hljs-string">"&lt;YOUR_PROXY_ADDRESS&gt;"</span>)

await contract.isV2()
-&gt; <span class="hljs-literal">true</span>
</code></pre>
<h3 id="heading-conclusion">Conclusion</h3>
<p>Congratulations if you made it until the end of this tutorial! You have now deployed an upgradable custom stablecoin with transaction fee redistribution to token holders. You have used <code>create3</code> to deploy all your contracts at static addresses across different chains.</p>
<p>If you were unable to code along you take a look at the completed code <a target="_blank" href="https://github.com/benjamin852/Advanced-ITS-Token/tree/complete">here</a>.</p>
<p>Interchain Token Service is a new initiative with the ability to provide simple cross-chain integration for your ERC20 token, we are excited to see what you will build with ITS.</p>
<p>If you have a new token you wish to deploy or an existing token you are looking to integrate with ITS you are more than welcome to reach out to <a target="_blank" href="https://www.interoplabs.io/">Interop Labs</a> team to see how we can help.</p>
]]></content:encoded></item><item><title><![CDATA[Building Multichain Stablecoins: Part One]]></title><description><![CDATA[As the web3 ecosystem continues to grow and more blockchains enter the industry, ensuring that your token is available on multiple chains is essential for the success of your application. What is also essential is that your token can be sent across t...]]></description><link>https://blog.axelar.dev/building-multichain-stablecoins-part-one</link><guid isPermaLink="true">https://blog.axelar.dev/building-multichain-stablecoins-part-one</guid><category><![CDATA[Blockchain]]></category><category><![CDATA[Web3]]></category><category><![CDATA[Solidity]]></category><category><![CDATA[axelar]]></category><category><![CDATA[Cryptocurrency]]></category><category><![CDATA[hardhat]]></category><category><![CDATA[ethers]]></category><category><![CDATA[Ethereum]]></category><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Ben Weinberg]]></dc:creator><pubDate>Mon, 22 Jul 2024 19:54:50 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1721336313461/7b04b5db-3759-40a0-abbf-d37fd8a878fe.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>As the web3 ecosystem continues to grow and more blockchains enter the industry, ensuring that your token is available on multiple chains is essential for the success of your application. What is also essential is that your token can be sent across these different chains to one another, rather than having siloed instances of your token across different chains. Axelar's Interchain Token Service is built to provide a solution for this.</p>
<p>This blog assumes you have an understanding of how to use Hardhat, a basic understanding of upgradable contracts, and how ERC20s operate.</p>
<p>Note: The token being built here contains many of the properties that can be used for a stablecoin such as transaction fee redistribution to token holders and transaction burning to contain inflation. The token will not contain all the components of a complete stablecoin. Rather the blog will focus more on the integration of the cross-chain components and testing of the token.</p>
<h3 id="heading-what-is-interchain-token-service">What is Interchain Token Service?</h3>
<p>The <a target="_blank" href="https://www.axelar.network/its">Interchain Token Service</a> (ITS) allows for the integration of tokens across many different blockchains. It can support the deployment of fresh new Interchain Tokens across multiple chains and it can also connect pre-existing custom ERC20s. ITS also comes with an easy-to-use <a target="_blank" href="https://interchain.axelar.dev/">frontend</a>, which offers a no-code solution for deploying your token across any connected chain that you choose.</p>
<h3 id="heading-objective">Objective</h3>
<p>In this blog, you will be focusing on custom ERC20 token integrations to ITS. Custom tokens can have more advanced functionality than the <a target="_blank" href="https://github.com/axelarnetwork/interchain-token-service/blob/main/contracts/interchain-token/InterchainToken.sol">InterchainTokens</a> that ITS deploys out of the box in its no-code solution. The token that you will be building will be an upgradable token that will be deployed using Axelar's <code>create3</code> service. The token will also have transaction fee redistribution to token holders and a burning mechanism, that burns a small percentage of each transaction to simulate inflation control.</p>
<p>In addition to the token itself, you will be using a <code>TokenFactory</code> contract that you will build out to deploy your token across different chains. There will be two types of tokens that will be built out, <code>NativeToken</code> and <code>SemiNativeToken</code>. The <code>NativeToken</code> will be the main token with the previously discussed features. The <code>SemiNativeToken</code> on the other hand will be a simpler ERC20 that will also be deployed through the factory. The reason for the two different tokens is to simulate a common issue, which teams in the stablecoin space face. Oftentimes, teams may be restricted to only officially operate on a certain group of chains, perhaps due to regulations or other restrictions. For the chains, that a team is regulated to operate on they can use the <code>NativeToken</code> but for those chains where they are not regulated, the simpler <code>SemiNativeToken</code> can be deployed by anyone via the <code>TokenFactory</code>. The <code>SemiNativeToken</code> will eventually be replaced by a <code>NativeToken</code> once the team is eligible to fully operate on that chain.</p>
<h3 id="heading-architecture">Architecture</h3>
<p>This project will be built using <a target="_blank" href="https://hardhat.org/">Hardhat</a> (but it can of course be built out with <a target="_blank" href="https://book.getfoundry.sh/">Foundry</a> as well). The five contracts you'll be interacting with are the <code>TokenFactory</code>, <code>TokenDeployer</code>, <code>NativeToken</code>, <code>SemiNativeToken</code>, and <code>AccessControl</code>.</p>
<p>Let's build!</p>
<p>Start by cloning the <a target="_blank" href="https://github.com/benjamin852/Advanced-ITS-Token">starter code</a>.</p>
<h3 id="heading-nativetoken">NativeToken</h3>
<p>You can begin by writing up the <code>NativeToken</code> contract.</p>
<p>Start by giving the token a name and importing the required <code>OpenZeppelin</code> helper contracts.</p>
<pre><code class="lang-solidity"><span class="hljs-comment">// SPDX-License-Identifier: MIT</span>
<span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> ^0.8.20;</span>

<span class="hljs-keyword">import</span> <span class="hljs-string">'@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20BurnableUpgradeable.sol'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20PausableUpgradeable.sol'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20PermitUpgradeable.sol'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol'</span>;

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">NativeToken</span> <span class="hljs-keyword">is</span>  <span class="hljs-title">Initializable</span>, <span class="hljs-title">ERC20Upgradeable</span>, <span class="hljs-title">ERC20BurnableUpgradeable</span>, <span class="hljs-title">ERC20PausableUpgradeable</span>, <span class="hljs-title">ERC20PermitUpgradeable</span> </span>{}
</code></pre>
<p>Next, go ahead and create the <code>initializer</code> for the token.</p>
<pre><code class="lang-solidity"> <span class="hljs-comment">/// @custom:oz-upgrades-unsafe-allow constructor</span>
    <span class="hljs-function"><span class="hljs-keyword">constructor</span>(<span class="hljs-params"></span>) </span>{
        _disableInitializers();
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">initialize</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title">initializer</span> </span>{
        __ERC20_init(<span class="hljs-string">'USD Token'</span>, <span class="hljs-string">'USD'</span>);
        __ERC20Burnable_init();
        __ERC20Pausable_init();
        __ERC20Permit_init(<span class="hljs-string">'USD Token'</span>);
    }
</code></pre>
<p>Once the initializer has been implemented you can implement two publicly available <code>mint()</code> and <code>burn()</code> functions.</p>
<pre><code class="lang-solidity"> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">mint</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> _to, <span class="hljs-keyword">uint256</span> _amount</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title">whenNotPaused</span> <span class="hljs-title">isBlacklisted</span>(<span class="hljs-params">_to</span>) </span>{
     _mint(_to, _amount);
 }

 <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">burn</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> _from, <span class="hljs-keyword">uint256</span> _amount</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title">whenNotPaused</span> </span>{
     _burn(_from, _amount);
 }
</code></pre>
<p>Note the <code>whenNotPaused</code> modifier on both the <code>mint()</code> and <code>burn()</code> functions which will be activated in case of an emergency.</p>
<p>You also need to override the <code>_update()</code> function. This function is written out in the <code>ERC20Upgradeable</code> contract that you're inheriting from. The <code>_update()</code> function is used when transferring a <code>value</code> amount of tokens from one address to another. You will need to eventually implement the custom burning and transaction fee logic in this function.</p>
<p>For now, implement it as follows:</p>
<pre><code class="lang-solidity">    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">_update</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> <span class="hljs-keyword">from</span>, <span class="hljs-keyword">address</span> to, <span class="hljs-keyword">uint256</span> value</span>)
        <span class="hljs-title"><span class="hljs-keyword">internal</span></span>
        <span class="hljs-title"><span class="hljs-keyword">override</span></span>(<span class="hljs-params">ERC20Upgradeable, ERC20PausableUpgradeable</span>) <span class="hljs-title">whenNotPaused</span>
    </span>{
        ERC20Upgradeable._update(<span class="hljs-keyword">from</span>, to, value);
    }
</code></pre>
<p>Great! At this point, you should have a working ERC20 token that can be upgradable!</p>
<p>Let's build this out a bit further. As mentioned before we want the token to have a <code>burnRate</code> for every transaction that is sent and a <code>fee</code> which will be paid out to token holders.</p>
<p>Set the <code>burnRate</code> and <code>txFeeRate</code> in storage as two public <code>uint256</code> variables. You can set a value for them in your <code>initialize()</code> function</p>
<p>Your contract should now look like this.</p>
<pre><code class="lang-solidity">    <span class="hljs-keyword">uint256</span> <span class="hljs-keyword">public</span> s_burnRate;
    <span class="hljs-keyword">uint256</span> <span class="hljs-keyword">public</span> s_txFeeRate;


    <span class="hljs-comment">/*************\
     INITIALIZATION
    /*************/</span>

    <span class="hljs-comment">/// @custom:oz-upgrades-unsafe-allow constructor</span>
    <span class="hljs-function"><span class="hljs-keyword">constructor</span>(<span class="hljs-params"></span>) </span>{
        _disableInitializers();
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">initialize</span>(<span class="hljs-params">
        <span class="hljs-keyword">uint256</span> _burnRate,
        <span class="hljs-keyword">uint256</span> _txFeeRate
    </span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title">initializer</span> </span>{
        __ERC20_init(<span class="hljs-string">'USD Token'</span>, <span class="hljs-string">'USD'</span>);
        __ERC20Burnable_init();
        __ERC20Pausable_init();
        __ERC20Permit_init(<span class="hljs-string">'USD Token USD'</span>);

        s_burnRate <span class="hljs-operator">=</span> _burnRate;
        s_txFeeRate <span class="hljs-operator">=</span> _txFeeRate;
    }
</code></pre>
<p>Now, back in your <code>_update()</code> function you can include some logic that will occur on every token transfer.</p>
<p>First, you set the <code>burnAmount</code> by multiplying the <code>value</code> of the transfer by the <code>s_burnRate</code> you set and then divide that by <code>1e18</code> (assuming your token has 18 decimal points). The same can be done for the transaction fee.</p>
<p>Now that you have the <code>burnAmount</code> and the <code>fee</code> you can subtract those two values from the actual amount being sent.</p>
<p>This can be written out as follows</p>
<pre><code class="lang-solidity">     <span class="hljs-keyword">uint256</span> burnAmount <span class="hljs-operator">=</span> (_value <span class="hljs-operator">*</span> s_burnRate) <span class="hljs-operator">/</span> <span class="hljs-number">1e18</span>;
     <span class="hljs-keyword">uint256</span> fee <span class="hljs-operator">=</span> (_value <span class="hljs-operator">*</span> s_txFeeRate) <span class="hljs-operator">/</span> <span class="hljs-number">1e18</span>;

     <span class="hljs-keyword">uint256</span> amountToSend <span class="hljs-operator">=</span> _value <span class="hljs-operator">-</span> fee <span class="hljs-operator">-</span> burnAmount;
</code></pre>
<p>Once you have the <code>amountToSend</code> you can burn the <code>burnAmount</code> and update a new storage variable called <code>s_rewardPool</code> with the fee.</p>
<p>Worth noting, is you only want to deduct these fees when a token is being transferred from one address to another as opposed to when a new token is being minted. The way to do this is to check if the <code>_from</code> address is <code>address(0)</code>. If it is, then <code>return</code> the function before calling the aforementioned functionality. The completed <code>_update()</code> function should be as follows.</p>
<pre><code class="lang-solidity">    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">_update</span>(<span class="hljs-params">
        <span class="hljs-keyword">address</span> _from,
        <span class="hljs-keyword">address</span> _to,
        <span class="hljs-keyword">uint256</span> _value
    </span>) <span class="hljs-title"><span class="hljs-keyword">internal</span></span> <span class="hljs-title"><span class="hljs-keyword">override</span></span>(<span class="hljs-params">ERC20Upgradeable, ERC20PausableUpgradeable</span>) <span class="hljs-title">whenNotPaused</span> </span>{
        <span class="hljs-keyword">if</span> (_from <span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-keyword">address</span>(<span class="hljs-number">0</span>)) {
            <span class="hljs-comment">// Minting case, do not apply burn and fee</span>
            ERC20Upgradeable._update(_from, _to, _value);
            <span class="hljs-keyword">return</span>;
        }
        <span class="hljs-keyword">uint256</span> burnAmount <span class="hljs-operator">=</span> (_value <span class="hljs-operator">*</span> s_burnRate) <span class="hljs-operator">/</span> <span class="hljs-number">1e18</span>;
        <span class="hljs-keyword">uint256</span> fee <span class="hljs-operator">=</span> (_value <span class="hljs-operator">*</span> s_txFeeRate) <span class="hljs-operator">/</span> <span class="hljs-number">1e18</span>;

        <span class="hljs-keyword">uint256</span> amountToSend <span class="hljs-operator">=</span> _value <span class="hljs-operator">-</span> fee <span class="hljs-operator">-</span> burnAmount;

        <span class="hljs-keyword">if</span> (burnAmount <span class="hljs-operator">&gt;</span> <span class="hljs-number">0</span>) _burn(_from, burnAmount);

        <span class="hljs-keyword">if</span> (amountToSend <span class="hljs-operator">+</span> burnAmount <span class="hljs-operator">+</span> fee <span class="hljs-operator">!</span><span class="hljs-operator">=</span> _value) <span class="hljs-keyword">revert</span> InvalidSendAmount();
        s_rewardPool <span class="hljs-operator">+</span><span class="hljs-operator">=</span> fee;
        ERC20Upgradeable._update(_from, _to, amountToSend);
        <span class="hljs-keyword">emit</span> RewardAdded(fee);
    }
</code></pre>
<p>Now that there is a reward pool accruing for token holders, you can include a simple <code>claimRewards()</code> function that allows token holders to claim a proportional reward for the number of tokens that they hold.</p>
<p>To calculate the reward you can check the balance of tokens that they have multiplied by the reward pool divided by the total supply of the token. Let's extract this into its own helper function called <code>_calculateReward()</code></p>
<pre><code class="lang-solidity">
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">_calculateReward</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> _account</span>) <span class="hljs-title"><span class="hljs-keyword">internal</span></span> <span class="hljs-title"><span class="hljs-keyword">view</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">uint256</span></span>) </span>{
        <span class="hljs-keyword">if</span> (totalSupply() <span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-number">0</span>) <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
        <span class="hljs-keyword">return</span> (s_rewardPool <span class="hljs-operator">*</span> balanceOf(_account)) <span class="hljs-operator">/</span> totalSupply();
    }
</code></pre>
<p>Now the <code>claimRewards()</code> function can call this function and mint an appropriate reward based on the output of the <code>calculateReward()</code> function. The <code>claimRewards()</code> function can be written as follows</p>
<pre><code class="lang-solidity">   <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">claimRewards</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title">whenNotPaused</span> </span>{
        <span class="hljs-keyword">uint256</span> reward <span class="hljs-operator">=</span> _calculateReward(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>);
        s_rewardPool <span class="hljs-operator">-</span><span class="hljs-operator">=</span> reward;
        _mint(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>, reward);
        <span class="hljs-keyword">emit</span> RewardClaimed(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>, reward);
    }
</code></pre>
<p>The final bit of functionality this token needs is the ability to alter these rates going forward. Let's add those functions as follows</p>
<pre><code class="lang-solidity">  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">setBurnRate</span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span> newBurnRate</span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title">whenNotPaused</span>  </span>{
        s_burnRate <span class="hljs-operator">=</span> newBurnRate;
  }

  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">setTxFee</span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span> newRewardRate</span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title">whenNotPaused</span>  </span>{
        s_txFeeRate <span class="hljs-operator">=</span> newRewardRate;
  }
</code></pre>
<p>Great! At this point, most of the token logic is now complete. The only issue you might want to restrict is who can call critical functions such as <code>setBurnRate</code> and <code>setTxFee()</code>.</p>
<h3 id="heading-accesscontrol">AccessControl</h3>
<p>To address this you will add a new contract called AccessControl. The AccessControl will inherit from OpenZeppelin's <code>AccessControlUpgradeable</code> contract.</p>
<p>The AccessControl contract will allow for several roles including <code>admin</code> role, <code>minter</code> role, and <code>blacklisted</code> role. You will need a <code>mapping</code> to track the different addresses that have been assigned to specific roles. The completed AccessControl will look something like this.</p>
<pre><code class="lang-solidity"><span class="hljs-comment">// SPDX-License-Identifier: MIT</span>
<span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> ^0.8.20;</span>

<span class="hljs-keyword">import</span> <span class="hljs-string">'@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol'</span>;

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">AccessControl</span> <span class="hljs-keyword">is</span> <span class="hljs-title">AccessControlUpgradeable</span> </span>{
    <span class="hljs-keyword">bytes32</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">constant</span> MINTER_ROLE <span class="hljs-operator">=</span> <span class="hljs-built_in">keccak256</span>(<span class="hljs-string">'MINTER_ROLE'</span>);
    <span class="hljs-keyword">bytes32</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">constant</span> PAUSER_ROLE <span class="hljs-operator">=</span> <span class="hljs-built_in">keccak256</span>(<span class="hljs-string">'PAUSER_ROLE'</span>);
    <span class="hljs-keyword">bytes32</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">constant</span> BLACKLIST_ADMIN_ROLE <span class="hljs-operator">=</span> <span class="hljs-built_in">keccak256</span>(<span class="hljs-string">'BLACKLIST_ADMIN_ROLE'</span>);

    <span class="hljs-comment">// eligible minters</span>
    <span class="hljs-keyword">mapping</span>(<span class="hljs-keyword">address</span> <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> <span class="hljs-keyword">bool</span>) <span class="hljs-keyword">private</span> _minterAddresses;

    <span class="hljs-comment">// blacklisted (receiver) addresses</span>
    <span class="hljs-keyword">mapping</span>(<span class="hljs-keyword">address</span> <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> <span class="hljs-keyword">bool</span>) <span class="hljs-keyword">private</span> _blacklistedAddresses;

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">initialize</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> _defaultAdmin</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title">initializer</span> </span>{
        __AccessControl_init();
        _grantRole(DEFAULT_ADMIN_ROLE, _defaultAdmin);
        _grantRole(MINTER_ROLE, _defaultAdmin);
        _grantRole(BLACKLIST_ADMIN_ROLE, _defaultAdmin);
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">addAdminRole</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> _address</span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title">onlyRole</span>(<span class="hljs-params">DEFAULT_ADMIN_ROLE</span>) </span>{
        grantRole(DEFAULT_ADMIN_ROLE, _address);
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">removeAdminRole</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> _address</span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title">onlyRole</span>(<span class="hljs-params">DEFAULT_ADMIN_ROLE</span>) </span>{
        revokeRole(DEFAULT_ADMIN_ROLE, _address);
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">addNewMinter</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> _address</span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title">onlyRole</span>(<span class="hljs-params">DEFAULT_ADMIN_ROLE</span>) </span>{
        _minterAddresses[_address] <span class="hljs-operator">=</span> <span class="hljs-literal">true</span>;
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">removeMinter</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> _address</span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title">onlyRole</span>(<span class="hljs-params">DEFAULT_ADMIN_ROLE</span>) </span>{
        _minterAddresses[_address] <span class="hljs-operator">=</span> <span class="hljs-literal">false</span>;
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">addToBlacklist</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> _address</span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title">onlyRole</span>(<span class="hljs-params">DEFAULT_ADMIN_ROLE</span>) </span>{
        _blacklistedAddresses[_address] <span class="hljs-operator">=</span> <span class="hljs-literal">true</span>;
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">removeFromBlacklist</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> _address</span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title">onlyRole</span>(<span class="hljs-params">DEFAULT_ADMIN_ROLE</span>) </span>{
        _blacklistedAddresses[_address] <span class="hljs-operator">=</span> <span class="hljs-literal">false</span>;
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">isAdmin</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> _address</span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title"><span class="hljs-keyword">view</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">bool</span></span>) </span>{
        <span class="hljs-keyword">return</span> hasRole(DEFAULT_ADMIN_ROLE, _address);
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">isWhitelistedMinter</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> _address</span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title"><span class="hljs-keyword">view</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">bool</span></span>) </span>{
        <span class="hljs-keyword">return</span> _minterAddresses[_address];
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">isBlacklistedReceiver</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> _address</span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title"><span class="hljs-keyword">view</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">bool</span></span>) </span>{
        <span class="hljs-keyword">return</span> _blacklistedAddresses[_address];
    }
}
</code></pre>
<p>Note: For blacklisting, we included a simplified <code>mapping</code> to collect any potential blacklisted addresses from receiving your token. In production, it would be recommended to use a service such as ChainAnalysis, which has an easy-to-use <a target="_blank" href="https://go.chainalysis.com/chainalysis-oracle-docs.html">Oracle</a> that you can integrate with your contract that tracks sanctioned addresses that regulators would prohibit your token from being sent to.</p>
<p>Now with your <code>AccessControl</code> set you can return to your <code>NativeToken</code> contract to integrate with the <code>AccessControl</code> contract.</p>
<p>First, you need to import the <code>AccessControl</code> contract to your token.</p>
<pre><code class="lang-solidity"><span class="hljs-keyword">import</span> <span class="hljs-string">'./AccessControl.sol'</span>;
</code></pre>
<p>Next, in the <code>initialize</code> function of your Token contract, make sure to pass in the address of your <code>AccessControl</code> contract and then store in a storage variable.</p>
<p>Your <code>initialize</code> function should now look like this.</p>
<pre><code class="lang-solidity">  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">initialize</span>(<span class="hljs-params">
        AccessControl _accessControl,
        <span class="hljs-keyword">uint256</span> _burnRate,
        <span class="hljs-keyword">uint256</span> _txFeeRate
    </span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title">initializer</span> </span>{
        __ERC20_init(<span class="hljs-string">'USD Token'</span>, <span class="hljs-string">'USD'</span>);
        __ERC20Burnable_init();
        __ERC20Pausable_init();
        __ERC20Permit_init(<span class="hljs-string">'USD Token'</span>);

        s_accessControl <span class="hljs-operator">=</span> _accessControl;

        s_burnRate <span class="hljs-operator">=</span> _burnRate;
        s_txFeeRate <span class="hljs-operator">=</span> _txFeeRate;
    }
</code></pre>
<p>Now you can add a <code>modifier</code> to use the <code>AccessControl</code> contract to restrict certain functionality to specific addresses granted a given role.</p>
<p>For example, <code>isAdmin</code> can restrict the <code>msg.sender</code> to be a specific whitelisted admin.</p>
<pre><code class="lang-solidity"> <span class="hljs-function"><span class="hljs-keyword">modifier</span> <span class="hljs-title">isAdmin</span>(<span class="hljs-params"></span>) </span>{
        <span class="hljs-keyword">if</span> (s_accessControl.isAdmin(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>)) <span class="hljs-keyword">revert</span> OnlyAdmin();
        <span class="hljs-keyword">_</span>;
    }
</code></pre>
<p>You can use the <code>isAdmin</code> modifier for your <code>setBurnRate()</code> and <code>setTxFeeRate()</code> modifiers.</p>
<p>Great! At this point, you should have all the functionality you need for your <code>NativeToken</code>! Now you need to deploy your token. For this, you can use a <code>Factory</code> contract to deploy the token on your home chain as well as other remote chains.</p>
<h3 id="heading-token-factory">Token Factory</h3>
<p>In this section, you will build the <code>TokenFactory</code> which will deploy the NativeToken you have just written on the home chain and also send a <a target="_blank" href="https://docs.axelar.dev/dev/general-message-passing/overview">General Message Passing (GMP message)</a> to a remote blockchain where you can deploy your token as well!</p>
<p>The factory will deploy a <a target="_blank" href="https://blog.openzeppelin.com/the-transparent-proxy-pattern">TransparentProxy</a> for your token so that your token is upgradable. It will also use <a target="_blank" href="https://www.axelar.network/blog/same-address-cross-chain-tutorial">create3</a> so that your token is at the same address across all chains that you choose to deploy on.</p>
<p>Much like the <code>NativeToken</code> contract, this contract will also be upgradable. So let's start with the <code>initialize</code> function.</p>
<p>The <code>initialize</code> function will take in several params including the address of the <code>InterchainTokenService</code>, the addresses of Axelar's <code>Gateway</code> and <code>GasService</code> contracts (which you will need for sending GMP messages), and the address of your <code>AccessControl</code> contract.</p>
<p>You will also need the appropriate storage variables to store these parameters in. Your <code>TokenFactory</code> contract should look like this now.</p>
<pre><code class="lang-solidity"><span class="hljs-keyword">import</span> <span class="hljs-string">'@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IAxelarGasService.sol'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IAxelarGateway.sol'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'@axelar-network/interchain-token-service/contracts/interfaces/IInterchainTokenService.sol'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol'</span>;  
<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">TokenFactory</span> </span>{   
    IInterchainTokenService <span class="hljs-keyword">public</span> s_its;
    AccessControl <span class="hljs-keyword">public</span> s_accessControl;
    IAxelarGasService <span class="hljs-keyword">public</span> s_gasService;
    IAxelarGateway <span class="hljs-keyword">public</span> s_gateway;    

    <span class="hljs-comment">/*************\
     INITIALIZATION
    /*************/</span>
    <span class="hljs-comment">/// @custom:oz-upgrades-unsafe-allow constructor</span>
    <span class="hljs-function"><span class="hljs-keyword">constructor</span>(<span class="hljs-params"></span>) </span>{
        _disableInitializers();
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">initialize</span>(<span class="hljs-params">
        IInterchainTokenService _its,
        IAxelarGasService _gasService,
        IAxelarGateway _gateway,
        AccessControl _accessControl,
    </span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title">initializer</span> </span>{
        s_its <span class="hljs-operator">=</span> _its;
        s_gasService <span class="hljs-operator">=</span> _gasService;
        s_gateway <span class="hljs-operator">=</span> _gateway;
        s_accessControl <span class="hljs-operator">=</span> _accessControl;
    }
}
</code></pre>
<p>With your <code>initializer</code> being built you can now move on to actually deploying the token.</p>
<p>Let's write a specific function for deploying the token on your <em>home</em> chain called <code>deployHomeNative()</code></p>
<p>Since your NativeToken requires a <code>burnRate</code> and <code>txFeeRate</code> you must make sure to pass that into your <code>deployHomeNative()</code> function to set those rates for the token. The function should look like this</p>
<pre><code class="lang-solidity"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">deployHomeNative</span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span> _burnRate, <span class="hljs-keyword">uint256</span> _txFeeRate</span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title">onlyAdmin</span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">address</span> newTokenProxy</span>) </span>{}
</code></pre>
<p>Note the <code>onlyAdmin</code> modifier can be defined exactly as you did previously in the Token contract so that only your team can deploy the original token on the home chain.</p>
<p>Before writing up the rest of this function you will need to import the <code>Create3.sol</code> contract from the <code>axelar-gmp-sdk</code> dependency. This will give you access to the <code>_create3()</code> function that you will use to deploy the contract. Import the dependency as follows</p>
<pre><code class="lang-solidity"><span class="hljs-keyword">import</span> <span class="hljs-string">'@axelar-network/axelar-gmp-sdk-solidity/contracts/deploy/Create3.sol'</span>;
</code></pre>
<p>Now with the dependency imported, you can have your contract inherit from the <code>Create3</code> contract.</p>
<p>When deploying with <code>create3()</code> you will need to pas in a <code>bytes32</code> salt, which will be used to determine the address of your contract. For simplicity you can defined to salts in the beginning of the <code>deployHomeNative()</code> function. The first salt can be for the deployment of your proxy and the second for the deployment of your implementation.</p>
<pre><code class="lang-solidity">
<span class="hljs-keyword">bytes32</span> SALT_PROXY <span class="hljs-operator">=</span> <span class="hljs-number">0x000000000000000000000000000000000000000000000000000000000000007B</span>; <span class="hljs-comment">//123</span>
<span class="hljs-keyword">bytes32</span> SALT_IMPL <span class="hljs-operator">=</span> <span class="hljs-number">0x00000000000000000000000000000000000000000000000000000000000004D2</span>; <span class="hljs-comment">//1234</span>
</code></pre>
<p>These hexes correspond to the numbers <code>123</code> for the proxy and <code>1234</code> for the implementation.</p>
<p>Next, you can deploy the <code>implementation</code> of the <code>NativeToken</code> contract. (Recall since the contract is going to be an upgradable contract you need to deploy both a proxy and implementation).</p>
<p>To deploy the <code>implementation</code> simply call the <code>_create3()</code> internal function, which is defined in the <code>Create3</code> contract that you inherited from before.</p>
<pre><code class="lang-solidity"><span class="hljs-comment">// Deploy implementation</span>
<span class="hljs-keyword">address</span> newTokenImpl <span class="hljs-operator">=</span> _create3(<span class="hljs-keyword">type</span>(NativeToken).<span class="hljs-built_in">creationCode</span>, SALT_IMPL);
<span class="hljs-keyword">if</span> (newTokenImpl <span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-keyword">address</span>(<span class="hljs-number">0</span>)) <span class="hljs-keyword">revert</span> DeploymentFailed();
</code></pre>
<p>The <code>_create3()</code> takes the deployment bytecode of the <code>NativeToken</code> contract and the salt that you already defined. You can then run a sanity check to make sure that the deployment was in fact successful and did not return a 0 address.</p>
<p>Now with your implementation contract deployed, you can move on to the <code>proxy</code>. Deploying the <code>proxy</code> will be a bit different than deploying the <code>implementation</code>, as you will technically be deploying a <a target="_blank" href="https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/proxy/transparent/TransparentUpgradeableProxy.sol">TransparentUpgradeableProxy</a> that is pointing to your implementation. To do this you can define a helper function called <code>_getEncodedCreationCodeNative()</code>.</p>
<p>This function will take in your <a target="_blank" href="https://docs.openzeppelin.com/contracts/4.x/api/proxy#ProxyAdmin">ProxyAdmin</a>, your <code>implementation</code> address, your <code>_burnRate</code>, and your <code>_txFeeRate</code>.</p>
<p>Your function signature should look like this</p>
<pre><code class="lang-solidity">
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">_getEncodedCreationCodeNative</span>(<span class="hljs-params">
        <span class="hljs-keyword">address</span> _proxyAdmin,
        <span class="hljs-keyword">address</span> _implAddr,
        <span class="hljs-keyword">uint256</span> _burnRate,
        <span class="hljs-keyword">uint256</span> _txFeeRate
    </span>) <span class="hljs-title"><span class="hljs-keyword">internal</span></span> <span class="hljs-title"><span class="hljs-keyword">view</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">bytes</span> <span class="hljs-keyword">memory</span> proxyCreationCode</span>) </span>{}
</code></pre>
<p>Now in this function, you can set your <code>initData</code> for the Token itself. Recall these are the three params that you required in your <code>initialize</code> function for the <code>NativeToken</code> contract (<code>accessControl</code>, <code>burnRate</code>, and <code>txFeeRate</code>). You can encode these three params into a single <code>bytes</code> variable that will be used when initializing your proxy</p>
<pre><code class="lang-solidity"><span class="hljs-keyword">bytes</span> <span class="hljs-keyword">memory</span> initData <span class="hljs-operator">=</span> <span class="hljs-built_in">abi</span>.<span class="hljs-built_in">encodeWithSelector</span>(NativeToken.initialize.<span class="hljs-built_in">selector</span>, s_accessControl, s_its, _burnRate, _txFeeRate);
</code></pre>
<p>Now (still in your <code>_getEncodedCreationCodeNative()</code> function). You can encode the <code>initData</code> you just defined along with the <code>_proxyAdmin</code> and the <code>_implAddr</code> that the <code>TransparentProxy</code> will require when it's being deployed. You can then encode that with the creation code of the <code>TransparentProxy</code> itself. This all translates into the following line of code</p>
<pre><code class="lang-solidity">proxyCreationCode <span class="hljs-operator">=</span> <span class="hljs-built_in">abi</span>.<span class="hljs-built_in">encodePacked</span>(<span class="hljs-keyword">type</span>(TransparentUpgradeableProxy).<span class="hljs-built_in">creationCode</span>, <span class="hljs-built_in">abi</span>.<span class="hljs-built_in">encode</span>(_implAddr, _proxyAdmin, initData));
</code></pre>
<p>So your completed <code>_getEncodedCreationCodeNative()</code> function now looks like this:</p>
<pre><code class="lang-solidity">    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">_getEncodedCreationCodeNative</span>(<span class="hljs-params">
        <span class="hljs-keyword">address</span> _proxyAdmin,
        <span class="hljs-keyword">address</span> _implAddr,
        <span class="hljs-keyword">uint256</span> _burnRate,
        <span class="hljs-keyword">uint256</span> _txFeeRate
    </span>) <span class="hljs-title"><span class="hljs-keyword">internal</span></span> <span class="hljs-title"><span class="hljs-keyword">view</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">bytes</span> <span class="hljs-keyword">memory</span> proxyCreationCode</span>) </span>{
        <span class="hljs-keyword">bytes</span> <span class="hljs-keyword">memory</span> initData <span class="hljs-operator">=</span> <span class="hljs-built_in">abi</span>.<span class="hljs-built_in">encodeWithSelector</span>(NativeToken.initialize.<span class="hljs-built_in">selector</span>, s_accessControl, s_its, _burnRate, _txFeeRate);

        proxyCreationCode <span class="hljs-operator">=</span> <span class="hljs-built_in">abi</span>.<span class="hljs-built_in">encodePacked</span>(<span class="hljs-keyword">type</span>(TransparentUpgradeableProxy).<span class="hljs-built_in">creationCode</span>, <span class="hljs-built_in">abi</span>.<span class="hljs-built_in">encode</span>(_implAddr, _proxyAdmin, initData));
    }
</code></pre>
<p>Back to your <code>deployHomeNative()</code> function you can now trigger the <code>_getEncodedCreationCodeNative()</code> function underneath where your deployed the <code>implementation</code> contract. The output of the <code>_getEncodedCreationCodeNative()</code> function will be the creation code of your proxy contract.</p>
<pre><code class="lang-solidity"><span class="hljs-keyword">bytes</span> <span class="hljs-keyword">memory</span> proxyCreationCode <span class="hljs-operator">=</span> _getEncodedCreationCodeNative(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>, newTokenImpl, _burnRate, _txFeeRate);
</code></pre>
<p>With the <code>proxyCreationCode</code> now available, you can call <code>_create3()</code> once again (exactly as you did for the implementation contract) and pass in the <code>proxyCreationCode</code> as the first parameter and the <code>SALT_PROXY</code> as the salt value. Let's also store the address of the deployed proxy in a storage variable called <code>s_nativeProxy</code>.</p>
<pre><code class="lang-solidity"><span class="hljs-comment">// Deploy the proxy</span>
newTokenProxy <span class="hljs-operator">=</span> _create3(proxyCreationCode, SALT_PROXY);
<span class="hljs-keyword">if</span> (newTokenProxy <span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-keyword">address</span>(<span class="hljs-number">0</span>)) <span class="hljs-keyword">revert</span> DeploymentFailed();

s_nativeToken <span class="hljs-operator">=</span> newTokenProxy;
</code></pre>
<p>Now that you have stored the address of the proxy you can go back to the top of the <code>deployHomeNative()</code> function and add in a quick check to make sure that no native token has been deployed before. If one has been deployed then you can <code>revert</code> the transaction.</p>
<pre><code class="lang-solidity"><span class="hljs-keyword">if</span> (s_nativeToken <span class="hljs-operator">!</span><span class="hljs-operator">=</span> <span class="hljs-keyword">address</span>(<span class="hljs-number">0</span>)) <span class="hljs-keyword">revert</span> TokenAlreadyDeployed();
</code></pre>
<p>Awesome! At this point once you call the <code>deployHomeNativeFunction()</code> you should now be able to deploy an upgradable version of the <code>NativeToken</code> stablecoin. But there is still more to do! Recall, that you want to be able to send cross-chain transactions with this token via ITS.</p>
<h4 id="heading-its-integration">ITS Integration</h4>
<p>To integrate your token with ITS you will need to deploy a token manager. A <a target="_blank" href="https://github.com/axelarnetwork/interchain-token-service/blob/main/contracts/token-manager/TokenManager.sol">Token Manager</a> is a separate contract that will help facilitate the integration of your token with ITS. Some of its responsibilities include setting flow limits (akin to rate limits) for your token, locking, burning, and minting tokens for cross-chain transactions. A token cannot send cross-chain transactions via ITS unless it has been successfully registered with its own unique token manager.</p>
<p>To deploy a token manager for your token you can simply call the function <code>deployTokenManager()</code> which is defined on the ITS contract that you passed into your <code>initialize</code> function.</p>
<p>The <code>deployTokenManager()</code> takes the <a target="_blank" href="https://github.com/axelarnetwork/interchain-token-service/blob/main/contracts/InterchainTokenService.sol#L270">following params</a>. First, it needs a salt, this salt will be used to generate your tokens unique <code>interchainTokenId</code>. This token will be used to track your authentic token deployment across all chains that your token is wired up to do cross-chain transfers. Next, you need to pass in the destination chain in case you're doing a cross-chain deployment of the token manager. In this case, you're deploying the token manager for the chain you're already on since there is no destination chain needed you can simply pass in an empty string here. You then need to pass in the <a target="_blank" href="https://github.com/axelarnetwork/interchain-token-service/blob/main/contracts/interfaces/ITokenManagerType.sol">type</a> of token manager you want. For this demo you can use the <code>LOCK_UNLOCK</code> token manager, this will lock your token on the home chain and unlock that token when it's bridged back from one of the remote chains. Next, you need to pass in the <code>params</code>. This is a <code>bytes</code> encoding of the address that will be the <code>operator</code> of the token and the address of the token itself. The <code>operator</code> is a role that allows a given address to adjust flow limits for the token. The fifth and final parameter is the <code>gasValue</code> this will be used to pay for the cost of a cross-chain token transfer, since you are doing a cross-chain deployment you can keep this as zero.</p>
<p>Still, in your <code>deployHomeNative()</code> function, you can call the <code>deployTokenManager()</code> function like this</p>
<pre><code class="lang-solidity">s_its.deployTokenManager(
    S_SALT_ITS_TOKEN,
    <span class="hljs-string">''</span>,
    ITokenManagerType.TokenManagerType.LOCK_UNLOCK,
    <span class="hljs-built_in">abi</span>.<span class="hljs-built_in">encode</span>(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>.toBytes(), newTokenProxy),
    <span class="hljs-number">0</span>
);
</code></pre>
<p>You can add a new event at the very bottom of the function to mark a successful token deployment and registration and that is it! The completed function should now look like this.</p>
<pre><code class="lang-solidity">    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">deployHomeNative</span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span> _burnRate, <span class="hljs-keyword">uint256</span> _txFeeRate</span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title">onlyAdmin</span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">address</span> newTokenProxy</span>) </span>{
        <span class="hljs-keyword">if</span> (s_nativeToken <span class="hljs-operator">!</span><span class="hljs-operator">=</span> <span class="hljs-keyword">address</span>(<span class="hljs-number">0</span>)) <span class="hljs-keyword">revert</span> TokenAlreadyDeployed();

        <span class="hljs-keyword">bytes32</span> SALT_PROXY <span class="hljs-operator">=</span> <span class="hljs-number">0x000000000000000000000000000000000000000000000000000000000000007B</span>; <span class="hljs-comment">//123</span>
        <span class="hljs-keyword">bytes32</span> SALT_IMPL <span class="hljs-operator">=</span> <span class="hljs-number">0x00000000000000000000000000000000000000000000000000000000000004D2</span>; <span class="hljs-comment">//1234</span>

        <span class="hljs-comment">// Deploy implementation</span>
        <span class="hljs-keyword">address</span> newTokenImpl <span class="hljs-operator">=</span> _create3(<span class="hljs-keyword">type</span>(NativeToken).<span class="hljs-built_in">creationCode</span>, SALT_IMPL);
        <span class="hljs-keyword">if</span> (newTokenImpl <span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-keyword">address</span>(<span class="hljs-number">0</span>)) <span class="hljs-keyword">revert</span> DeploymentFailed();

        <span class="hljs-comment">// Generate Proxy Creation Code</span>
        <span class="hljs-keyword">bytes</span> <span class="hljs-keyword">memory</span> proxyCreationCode <span class="hljs-operator">=</span> _getEncodedCreationCodeNative(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>, newTokenImpl, _burnRate, _txFeeRate);

        <span class="hljs-comment">// Deploy proxy</span>
        newTokenProxy <span class="hljs-operator">=</span> _create3(proxyCreationCode, SALT_PROXY);
        <span class="hljs-keyword">if</span> (newTokenProxy <span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-keyword">address</span>(<span class="hljs-number">0</span>)) <span class="hljs-keyword">revert</span> DeploymentFailed();
        s_nativeToken <span class="hljs-operator">=</span> newTokenProxy;

        <span class="hljs-comment">// Deploy ITS</span>
        <span class="hljs-keyword">bytes32</span> tokenId <span class="hljs-operator">=</span> s_its.deployTokenManager(
            S_SALT_ITS_TOKEN,
            <span class="hljs-string">''</span>,
            ITokenManagerType.TokenManagerType.LOCK_UNLOCK,
            <span class="hljs-built_in">abi</span>.<span class="hljs-built_in">encode</span>(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>.toBytes(), newTokenProxy),
            <span class="hljs-number">0</span>
        );

        <span class="hljs-keyword">emit</span> NativeTokenDeployed(newTokenProxy, tokenId);
    }
</code></pre>
<p>Great! At this point when this function is called you will have successfully deployed an upgradeable <code>NativeToken</code> AND connected it to the Interchain Token Service!</p>
<h3 id="heading-conclusion">Conclusion</h3>
<p>In this section, you have built a custom ERC20 token that can burn tokens at a set burn rate for each token transfer and accrue proportional rewards for token holders. The token's roles are controlled by the Access Control contract. Finally, you wrote up a factory contract to deploy your custom token as an upgradable token using <code>create3</code> to have a predictable contract address and integrated your newly deployed token with ITS.</p>
<p>In <a target="_blank" href="https://blog.axelar.dev/building-multichain-stablecoins-part-two">part two</a>, you will continue to build out your Token Factory so that you can deploy your custom token on other blockchains.</p>
<p>The complete code for this section can be found <a target="_blank" href="https://github.com/benjamin852/Multichain-Stablecoin/tree/complete-p1">here</a>.</p>
]]></content:encoded></item><item><title><![CDATA[How to fix command not found: axelard / tofnd]]></title><description><![CDATA[If you have followed the Axelar setup instructions for getting axelard and tofnd but keep running into a command not found error, try navigating to the folder your binary is in and referring directly to that binary instead of setting up an alias.
Mak...]]></description><link>https://blog.axelar.dev/how-to-fix-command-not-found-axelard-tofnd</link><guid isPermaLink="true">https://blog.axelar.dev/how-to-fix-command-not-found-axelard-tofnd</guid><category><![CDATA[axelar]]></category><category><![CDATA[error handling]]></category><category><![CDATA[debugging]]></category><category><![CDATA[Linux]]></category><dc:creator><![CDATA[Marty]]></dc:creator><pubDate>Wed, 17 Jul 2024 15:12:45 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1721226361574/43ce24a5-994f-412f-a6b9-baf5d4789bf4.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you have followed the <a target="_blank" href="https://docs.axelar.dev/validator/setup/manual">Axelar setup instructions</a> for getting <code>axelard</code> and <code>tofnd</code> but keep running into a command not found error, try navigating to the folder your binary is in and referring directly to that binary instead of setting up an alias.</p>
<p>Make sure that you have done the following first:</p>
<ul>
<li><p><a target="_blank" href="https://docs.google.com/document/d/1eV8zdI2PstCTPRzetUfoSrzXptZ0LF3Hz4lBkYMX9uc/edit#heading=h.5p12l7pc8kis">Downloaded the axelard binary</a> and made it executable with <code>chmod a+x axelard</code> </p>
</li>
<li><p><a target="_blank" href="https://docs.google.com/document/d/1eV8zdI2PstCTPRzetUfoSrzXptZ0LF3Hz4lBkYMX9uc/edit#heading=h.5p12l7pc8kis">Downloaded the tofnd binary</a> and made it executable with <code>chmod a+x tofnd-darwin-[version]</code></p>
</li>
<li><p><a target="_blank" href="https://docs.google.com/document/d/1eV8zdI2PstCTPRzetUfoSrzXptZ0LF3Hz4lBkYMX9uc/edit#heading=h.5p12l7pc8kis">Downloaded the wasmvm (libwasmvm) library</a></p>
</li>
</ul>
<p>The solution is simple:  Don’t symlink or create an alias to the binary. Just <code>cd</code> into the directory that your executable binary is in and run it with its full name.</p>
<p>For example, if you have the executable <code>axelard</code> binary in your <code>Downloads</code> folder, cd into the <code>Downloads</code> folder  and run <code>./axelard version</code> instead of running <code>axelard version</code> from any folder.</p>
<p>To check that things are working:</p>
<ul>
<li><p>Instead of <code>axelard version</code>, run <code>./axelard version</code></p>
</li>
<li><p>Instead of <code>axelard q wasm libwasmvm-version</code>, run <code>./axelard q wasm libwasmvm-version</code></p>
</li>
<li><p>Instead of <code>tofnd --help</code>, run <code>tofnd-darwin-[version] --help</code></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[June 2024 Dev Update: 🔥 2M Cross-Chain Transactions 🔥 Interchain Amplifier, ITS Farcaster Frame with Axelar GMP  🏗️]]></title><description><![CDATA[Welcome to the June 2024 Axelar Developer Newsletter. You can subscribe to the Axelar Developer Newsletter to get direct updates.

Celebrating 2 Million Cross-Chain Transactions and 13 million Blocks

Special thanks to all the protocols, builders, an...]]></description><link>https://blog.axelar.dev/june-2024-dev-update-2m-cross-chain-transactions-interchain-amplifier-its-farcaster-frame-with-axelar-gmp</link><guid isPermaLink="true">https://blog.axelar.dev/june-2024-dev-update-2m-cross-chain-transactions-interchain-amplifier-its-farcaster-frame-with-axelar-gmp</guid><category><![CDATA[Web3]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[Smart Contracts]]></category><category><![CDATA[farcaster]]></category><category><![CDATA[axelar]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Developer]]></category><dc:creator><![CDATA[Idris Olubisi]]></dc:creator><pubDate>Fri, 28 Jun 2024 14:31:47 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1719584897831/fa9c2ae8-5333-4677-804b-291d721b44e0.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Welcome to the June 2024 Axelar Developer Newsletter. You can subscribe to the <a target="_blank" href="https://dashboard.mailerlite.com/forms/215012/103202424602232757/share">Axelar Developer Newsletter</a> to get direct updates.</p>
<p><img src="https://lh7-us.googleusercontent.com/docsz/AD_4nXcKV0E5xUi2aYezuESMXY24E2bnxXS3eiCQ5iT7fXfSmd1GcY7x8tVRVX9Wbrg5WCsn7GageJPo29U-uS64hMEGDBlVTAyby0UuxeeKwGWjgsvzfo_-HkZj1S2J7wacyahi5gxSqq7aRxxqlpEWY8Y6baA?key=9EL9oPbbyIK7KIFZfrvJJw" alt /></p>
<h2 id="heading-celebrating-2-million-cross-chain-transactions-and-13-million-blocks">Celebrating 2 Million Cross-Chain Transactions and 13 million Blocks</h2>
<p><img src="https://lh7-us.googleusercontent.com/docsz/AD_4nXfBzZGaEufr51VMClgBPw_B__5gI_qNZm-gCTOV-b45H1OYTRuuJaPlLpO3vvQwNzEQlL3s2lC1HNUHMEoTx8DjQKHQ7IdJGVTse0pUG97kgy1qxEdb7lPx4SomV-wtE0Uv5OVZSIWFWtFcBiqb9FE_rTXU?key=9EL9oPbbyIK7KIFZfrvJJw" alt /></p>
<p>Special thanks to all the protocols, builders, and early adopters who have contributed to the growth of the Axelar ecosystem! We now have over 1.5 million testnet <a target="_blank" href="https://testnet.axelarscan.io/">transactions</a>. 🦾 This is just the beginning ⏩ Visit <a target="_blank" href="https://axelarscan.io">https://axelarscan.io</a> for more.</p>
<h2 id="heading-developer-content-highlights"><strong>Developer Content Highlights</strong></h2>
<p><img src="https://lh7-us.googleusercontent.com/docsz/AD_4nXfpKQLPQqbtDVXcMeGxUb5p6s2SyMbf_4h69np4mmnF4Orwfgf8nAeJ0kUQpoHWfhHLv8OwmfVyK7BRMsb5nGReQwW-OoCv9EIJS2cq9aafAI16uQluskUHDQM28fHGXpZ1UMMFrmjJk-tDgmdoR8o7drw?key=9EL9oPbbyIK7KIFZfrvJJw" alt /></p>
<p>We've just published several relevant technical articles and documentation updates.</p>
<h3 id="heading-amplifier"><strong>Amplifier</strong></h3>
<ul>
<li><p><a target="_blank" href="https://obgjzx.clicks.mlsend.com/ty/cl/eyJ2Ijoie1wiYVwiOjIxNTAxMixcImxcIjoxMjUzOTIyODE1MDQwNTYzNzMsXCJyXCI6MTI1MzkyMjg5MTkyMjE2MjE5fSIsInMiOiIzN2RkMzBhN2UwOWIxZWY4In0">Verifier rewards:</a> Understand the Amplifier rewards contract.</p>
</li>
<li><p><a target="_blank" href="https://obgjzx.clicks.mlsend.com/ty/cl/eyJ2Ijoie1wiYVwiOjIxNTAxMixcImxcIjoxMjUzOTIyODE1MDkyOTkyNTQsXCJyXCI6MTI1MzkyMjg5MTkyMjE2MjE5fSIsInMiOiJkNDM4ODliNWVjOGMyN2Q3In0">Rewards for Amplifier cha</a><a target="_blank" href="https://obgjzx.clicks.mlsend.com/ty/cl/eyJ2Ijoie1wiYVwiOjIxNTAxMixcImxcIjoxMjUzOTIyODE1MDQwNTYzNzMsXCJyXCI6MTI1MzkyMjg5MTkyMjE2MjE5fSIsInMiOiIzN2RkMzBhN2UwOWIxZWY4In0">in integrators:</a> Learn how to add funds to the rewards pool of an Amplifier-integrated chain.</p>
</li>
</ul>
<h3 id="heading-its"><strong>ITS</strong></h3>
<ul>
<li><a target="_blank" href="https://obgjzx.clicks.mlsend.com/ty/cl/eyJ2Ijoie1wiYVwiOjIxNTAxMixcImxcIjoxMjUzOTIyODE1MDkyOTkyNTQsXCJyXCI6MTI1MzkyMjg5MTkyMjE2MjE5fSIsInMiOiJkNDM4ODliNWVjOGMyN2Q3In0">Interchain Token S</a><a target="_blank" href="https://obgjzx.clicks.mlsend.com/ty/cl/eyJ2Ijoie1wiYVwiOjIxNTAxMixcImxcIjoxMjUzOTIyODE1MDQwNTYzNzMsXCJyXCI6MTI1MzkyMjg5MTkyMjE2MjE5fSIsInMiOiIzN2RkMzBhN2UwOWIxZWY4In0">ervice Roadmap:</a> Our roadmap includes migrations to governance, deploying advanced token management features, and expanding support for more chains.</li>
</ul>
<h3 id="heading-axelar-gas-service"><strong>Axelar Gas Service</strong></h3>
<ul>
<li><a target="_blank" href="https://obgjzx.clicks.mlsend.com/ty/cl/eyJ2Ijoie1wiYVwiOjIxNTAxMixcImxcIjoxMjUzOTIyODE1MjE4ODIxNjgsXCJyXCI6MTI1MzkyMjg5MTkyMjE2MjE5fSIsInMiOiJmYmQ2MTUxNGU0OWE3NmM1In0">Est</a><a target="_blank" href="https://obgjzx.clicks.mlsend.com/ty/cl/eyJ2Ijoie1wiYVwiOjIxNTAxMixcImxcIjoxMjUzOTIyODE1MDQwNTYzNzMsXCJyXCI6MTI1MzkyMjg5MTkyMjE2MjE5fSIsInMiOiIzN2RkMzBhN2UwOWIxZWY4In0">imate and Pay Ga</a><a target="_blank" href="https://obgjzx.clicks.mlsend.com/ty/cl/eyJ2Ijoie1wiYVwiOjIxNTAxMixcImxcIjoxMjUzOTIyODE1MjE4ODIxNjgsXCJyXCI6MTI1MzkyMjg5MTkyMjE2MjE5fSIsInMiOiJmYmQ2MTUxNGU0OWE3NmM1In0">s:</a> Learn how gas estimation works, types of Axelar gas <a target="_blank" href="https://obgjzx.clicks.mlsend.com/ty/cl/eyJ2Ijoie1wiYVwiOjIxNTAxMixcImxcIjoxMjUzOTIyODE1MjE4ODIxNjgsXCJyXCI6MTI1MzkyMjg5MTkyMjE2MjE5fSIsInMiOiJmYmQ2MTUxNGU0OWE3NmM1In0"></a>payment and how you can pay gas</li>
</ul>
<h3 id="heading-additional-chain-support"><strong>Additional chain support</strong></h3>
<ul>
<li><a target="_blank" href="https://obgjzx.clicks.mlsend.com/ty/cl/eyJ2Ijoie1wiYVwiOjIxNTAxMixcImxcIjoxMjUzOTIyODE1MDQwNTYzNzMsXCJyXCI6MTI1MzkyMjg5MTkyMjE2MjE5fSIsInMiOiIzN2RkMzBhN2UwOWIxZWY4In0">Axelar Adds S</a><a target="_blank" href="https://obgjzx.clicks.mlsend.com/ty/cl/eyJ2Ijoie1wiYVwiOjIxNTAxMixcImxcIjoxMjUzOTIyODE1MjcxMjUwNDksXCJyXCI6MTI1MzkyMjg5MTkyMjE2MjE5fSIsInMiOiI3ZGYyMThmYzFhZmU3ZTRlIn0">upport for Polygon Amoy and Linea Sepolia:</a> Axelar now supports Polygon Amoy (Sepolia) and Linea Sepolia on testnet.</li>
</ul>
<h2 id="heading-developer-event-highlights"><strong>Developer Event Highlights</strong></h2>
<p><img src="https://lh7-us.googleusercontent.com/docsz/AD_4nXfwKfQRBSiBxU-72W2fyTGPSKR4n9MCI9dBXSc4Y6-5y0CbDVY9xhLZmGOEuvudUl1mAQ_s3dOb8k6AY53IPhjZ_aRpszLIF4Rd-g0kn2SFcoF1sNIF3nLfSAN01P4V7SH_2QgrHcqcDaL6t2GNKcDFXPA2?key=9EL9oPbbyIK7KIFZfrvJJw" alt /></p>
<p>The Axelar team has been traveling the world to empower developers. Here are a few highlights from our talks:</p>
<ul>
<li><p><a target="_blank" href="https://obgjzx.clicks.mlsend.com/ty/cl/eyJ2Ijoie1wiYVwiOjIxNTAxMixcImxcIjoxMjUzOTIyODE1MjE4ODIxNjgsXCJyXCI6MTI1MzkyMjg5MTkyMjE2MjE5fSIsInMiOiJmYmQ2MTUxNGU0OWE3NmM1In0">Build</a> <a target="_blank" href="https://obgjzx.clicks.mlsend.com/ty/cl/eyJ2Ijoie1wiYVwiOjIxNTAxMixcImxcIjoxMjUzOTIyODE1MjcxMjUwNDksXCJyXCI6MTI1MzkyMjg5MTkyMjE2MjE5fSIsInMiOiI3ZGYyMThmYzFhZmU3ZTRlIn0">a Farc</a><a target="_blank" href="https://www.youtube.com/watch?v=dmM1M2LM_zQ">aster Frame to bridge ERC-20 token with ITS</a></p>
</li>
<li><p><a target="_blank" href="https://youtu.be/gIh4j8iQAN8?t=7511">Lagos Blockchain week</a></p>
</li>
<li><p><a target="_blank" href="https://www.youtube.com/watch?v=ZHsA1KDxyeo">Send Cross-</a><a target="_blank" href="https://obgjzx.clicks.mlsend.com/ty/cl/eyJ2Ijoie1wiYVwiOjIxNTAxMixcImxcIjoxMjUzOTIyODE1MjE4ODIxNjgsXCJyXCI6MTI1MzkyMjg5MTkyMjE2MjE5fSIsInMiOiJmYmQ2MTUxNGU0OWE3NmM1In0">chain Messages with</a> <a target="_blank" href="https://www.youtube.com/watch?v=ZHsA1KDxyeo">Axelar G</a><a target="_blank" href="https://obgjzx.clicks.mlsend.com/ty/cl/eyJ2Ijoie1wiYVwiOjIxNTAxMixcImxcIjoxMjUzOTIyODE1MjE4ODIxNjgsXCJyXCI6MTI1MzkyMjg5MTkyMjE2MjE5fSIsInMiOiJmYmQ2MTUxNGU0OWE3NmM1In0">MP</a></p>
</li>
</ul>
<h2 id="heading-upcoming-event-how-to-build-an-advanced-its-token">Upcoming event: How to Build an Advanced ITS Token</h2>
<p>In this workshop, you will learn about building advanced cross-chain contracts with ITS. Join us for a walkthrough on how to build a customized ERC20 token equipped with cross-chain functionality. We will then deploy an upgradeable token with advanced functionality. </p>
<p>Inspired by real-world use cases, the token can take two forms: an advanced token for chains where regulators may approve you to operate and a more straightforward canonical token that can be upgraded to the more advanced token when you're approved to operate on that chain.</p>
<p>Don’t forget to set a reminder <a target="_blank" href="https://www.youtube.com/watch?v=omaO6u4p8xA">here</a> for the event!</p>
<p>We have a lot more planned for the upcoming months, so you don’t want to miss out. To stay up to date on the latest Axelar news, make sure you are <a target="_blank" href="https://obgjzx.clicks.mlsend.com/te/cl/eyJ2Ijoie1wiYVwiOjIxNTAxMixcImxcIjoxMDU0NTg5MjgyODI3NjQ0NzcsXCJyXCI6MTA1NDU4OTU3NjQwNzk1Njc5fSIsInMiOiJiMTA2MzFhZmZmYTA4Yzk4In0">subscribed</a> to this Developer Newsletter.</p>
]]></content:encoded></item><item><title><![CDATA[Axelar Adds Support for Polygon Amoy and Linea Sepolia]]></title><description><![CDATA[As a developer building decentralized applications and smart contracts, a testnet acts as your production environment. It allows you to build, test, and deploy before moving to the mainnet, providing a safe and secure environment for testing your app...]]></description><link>https://blog.axelar.dev/axelar-adds-support-for-polygon-amoy-and-linea-sepolia</link><guid isPermaLink="true">https://blog.axelar.dev/axelar-adds-support-for-polygon-amoy-and-linea-sepolia</guid><category><![CDATA[Polygon]]></category><category><![CDATA[axelar]]></category><category><![CDATA[linea]]></category><category><![CDATA[Blockchain]]></category><category><![CDATA[Web3]]></category><category><![CDATA[Smart Contracts]]></category><dc:creator><![CDATA[Idris Olubisi]]></dc:creator><pubDate>Thu, 06 Jun 2024 11:17:29 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1717590823010/da3e065a-879b-4d81-9ba5-2013034a4f7f.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>As a developer building decentralized applications and smart contracts, a testnet acts as your production environment. It allows you to build, test, and deploy before moving to the mainnet, providing a safe and secure environment for testing your application.</p>
<p>The Ethereum community maintains two primary public testnets: Sepolia, one of Ethereum’s most prominent proof-of-stake (PoS) testnets, and Goerli, which was <a target="_blank" href="https://blog.ethereum.org/2023/11/30/goerli-lts-update">recently sunsetted</a>.</p>
<p>We are happy to announce that Axelar now supports Polygon Amoy (Sepolia) and Linea Sepolia on testnet. This follows our previous announcement, "<a target="_blank" href="https://blog.axelar.dev/goerli-deprecation-and-new-ethereum-sepolia-layer-2-sepolia-support-with-axelar">Goerli Deprecation and New Ethereum Sepolia, Layer 2 Sepolia Support with Axelar</a>," aimed at continuing our support for developers building innovative applications. Check the full list of supported networks <a target="_blank" href="https://docs.axelar.dev/resources/contract-addresses/testnet">here</a>.</p>
<h2 id="heading-sepolia-test-network-on-axelar">Sepolia Test Network on Axelar</h2>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Name</td><td>Chain Name</td></tr>
</thead>
<tbody>
<tr>
<td>Ethereum Sepolia</td><td>11155111</td></tr>
<tr>
<td>Arbitrum Sepolia</td><td>421614</td></tr>
<tr>
<td>Optimism Sepolia Testnet</td><td>11155420</td></tr>
<tr>
<td>Base Sepolia Testnet</td><td>84532</td></tr>
<tr>
<td>Blast Sepolia Testnet</td><td>168587773</td></tr>
<tr>
<td>Mantle Sepolia</td><td>5003</td></tr>
<tr>
<td>Polygon Amoy</td><td>80002</td></tr>
<tr>
<td>Linea Sepolia</td><td>59141</td></tr>
<tr>
<td></td></tr>
</tbody>
</table>
</div><p>The deprecation of Goerli and the shift towards Sepolia and L2 support represent a significant milestone in Ethereum's development. These changes underscore our commitment to providing our community with the most advanced and efficient tools.</p>
<p>We understand that transitions can be challenging, but we are here to support you every step of the way. Our team is committed to making the transition smooth for developers and users. We provide resources, documentation, and support throughout the process. Please open an issue on our <a target="_blank" href="https://github.com/axelarnetwork/support">Github support repository</a> if you need additional help.</p>
<p>Stay tuned for more updates, and thank you for being a part of this journey with us.</p>
]]></content:encoded></item><item><title><![CDATA[May 2024 Dev Update: Interchain Amplifier on Devnet, Onboard Your IBC Chain, Farcaster Frame with Axelar GMP  🏗️]]></title><description><![CDATA[Axelar Interchain Amplifier now integrates with Rollkit

The Axelar Foundation has announced an integration with Celestia Labs, simplifying multichain interoperability for sovereign blockchains built with Rollkit, the first sovereign rollup framework...]]></description><link>https://blog.axelar.dev/may-2024-dev-update-interchain-amplifier-on-devnet-onboard-your-ibc-chain-farcaster-frame-with-axelar-gmp</link><guid isPermaLink="true">https://blog.axelar.dev/may-2024-dev-update-interchain-amplifier-on-devnet-onboard-your-ibc-chain-farcaster-frame-with-axelar-gmp</guid><category><![CDATA[axelar]]></category><category><![CDATA[frame]]></category><category><![CDATA[development]]></category><category><![CDATA[Blockchain]]></category><category><![CDATA[farcaster]]></category><category><![CDATA[IBC]]></category><dc:creator><![CDATA[Idris Olubisi]]></dc:creator><pubDate>Thu, 30 May 2024 11:52:21 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1717069727173/d9be46f5-106e-49b5-b2fc-d8e5aa7eca84.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><img src="https://lh7-us.googleusercontent.com/E2Z1T_v3voXT1p6FtNtblXQjwhzLJEXJt3nX8qc7rlIA4ZmyzvH_7LcC-qOJV5X5eJSpAI45up67NZolbJcIUa9H0al3AqTY8_UxHPY3brbmi4cQZ64tQY6cuR-j2EsJYru3poz7oWNwOn8x7TTCbmE" alt /></p>
<h2 id="heading-axelar-interchain-amplifier-now-integrates-with-rollkit">Axelar Interchain Amplifier now integrates with Rollkit</h2>
<p><img src="https://lh7-us.googleusercontent.com/HU_Bj-ItqYpWJXWrC9C9Tw_WDaOFH4DMpG9IDP6MvunWXiLqLucH-pZDRJHA3-u6I7Zk9QlO9Di2DPqfp9W7zUTloKlpshXuVBewtcdCETulcQwWQjpYVahMwmpKmAkTj2RKJLv2cobdzukRFjipmlc" alt /></p>
<p>The Axelar Foundation has <a target="_blank" href="https://www.axelar.network/blog/celestia-rollkit-interoperability">announced an integration with Celestia Labs</a>, simplifying multichain interoperability for sovereign blockchains built with Rollkit, the first sovereign rollup framework. This collaboration supports the modular blockchain vision, enabling seamless multichain development for new blockchains.</p>
<p>This integration of Rollkit and Axelar Interchain Amplifier will introduce interoperability toolkits connecting rollups across EVM, Cosmos, Bitcoin, Polkadot, and beyond. Interop Labs, the initial developer of the Axelar network, will build the necessary smart contracts and tooling to integrate Interchain Amplifier with Rollkit, further advancing Web3 scalability and user experience.</p>
<p>ICYMI: <a target="_blank" href="https://obgjzx.clicks.mlsend.com/tb/cl/eyJ2Ijoie1wiYVwiOjIxNTAxMixcImxcIjoxMjI3MjM2MTgyNDk1MDg2MjYsXCJyXCI6MTIyNzIzNjY0MjY1MjE3MTY5fSIsInMiOiIxYjk1ZDUzMjMxMDQ5ZTEzIn0">Axelar Interchain Amplifier: Now live on Devnet!</a></p>
<h2 id="heading-developer-content-highlights"><strong>Developer Content Highlights</strong></h2>
<p><img src="https://lh7-us.googleusercontent.com/tB4kYjjPKXh01cJJPRfYhewdIvcjGSMr7kMTQxAMKevvFtB--e1OeMpy9i51gnsNx1PhcQLoWAFtuM4XdCKYNM0lYixIysdasSJuKEgD8W1Znza5yvtSnZJZk_LB3KYa0yXnc6qVWEFTAygSKG8-s6k" alt /></p>
<p>We've just published several relevant technical articles and documentation updates:</p>
<ul>
<li><p><a target="_blank" href="https://docs.axelar.dev/resources/ibc-chain-onboarding">Onboard your IBC-compatible chain</a>: Follow these steps to onboard your Cosmos or IBC-compatible chain to the Axelar network.</p>
</li>
<li><p><a target="_blank" href="https://docs.axelar.dev/dev/general-message-passing/executable">Axelar Executable Overview</a>: Learn about the Axelar Executable Contract, a component of the Axelar General Message Passing (GMP) flow.</p>
</li>
<li><p><a target="_blank" href="https://blog.axelar.dev/test-its-locally-with-axelar-examples">Test ITS locally with Axelar Examples</a>: Learn how to test Interchain Token Service locally with the axelar-examples repository.</p>
</li>
</ul>
<h2 id="heading-events-weve-attended">Events we’ve attended</h2>
<p><img src="https://lh7-us.googleusercontent.com/69sekAvJQdaw1y0H6f7HZFnRf-jyYeOmaPjeEvkty3Yk5k3gRI8ZGi-67mWH-6c6AHD5kzhQy8zfYrf6FikPaVn5-iswExSAJtX6YZ_8z0TmsMNCcP8d6tNF74uRbMbJjzMpUaOO7Yy_-K4QUYHYJFY" alt class="image--center mx-auto" /></p>
<p>The Axelar team has been traveling the world to empower developers. Here are a few highlights from our talks:</p>
<ul>
<li><p><a target="_blank" href="https://www.youtube.com/watch?v=ZHsA1KDxyeo">Send Cross-chain Messages with Axelar GMP</a></p>
</li>
<li><p><a target="_blank" href="https://x.com/Official_NODO/status/1785631354723422632">Lisk Blockchain Incubation event</a></p>
</li>
<li><p><a target="_blank" href="https://twitter.com/_olanetsoft/status/1789561261224583650?t=GPORS5AkjZA-0O0zdAB-Tg&amp;s=19">Ethereum Frontiers Africa event with Vitalik and Ethereum core team</a></p>
</li>
<li><p><a target="_blank" href="https://youtu.be/-BLxkNvtmOc?t=11458">Til conf - Building the future of Web: From Websites to dApp with JavaScript</a></p>
<h2 id="heading-upcoming-event-build-a-farcaster-frame-to-send-multichain-messages-with-axelar-gmp">Upcoming event: Build a Farcaster Frame to Send Multichain Messages with Axelar GMP</h2>
</li>
</ul>
<p><img src="https://lh7-us.googleusercontent.com/BVIqPrDGG8n8BqEnv3lz3JeXER4cvK8FsAcnaO8djk_Oq0ApFBHn49p9k80oexqGLxD1wHV0k6ZXJjEEOgEBZr6Jj6UlHzsDLc6GevRp-ULlcjo6WfmO8hFoR03deNzgEfwqEASJY1Ge63D7mcx-oPs" alt /></p>
<p>In this workshop, you will learn about building Farcaster frames and building a multichain messaging frame with Axelar GMP.</p>
<p>Don’t forget to <a target="_blank" href="https://www.youtube.com/watch?v=M6JfvY4-APE">set a reminder</a> for the event!</p>
<p>We have a lot more planned for the upcoming months, so you don’t want to miss out. To stay up to date on the latest Axelar news, make sure you are <a target="_blank" href="https://obgjzx.clicks.mlsend.com/te/cl/eyJ2Ijoie1wiYVwiOjIxNTAxMixcImxcIjoxMDU0NTg5MjgyODI3NjQ0NzcsXCJyXCI6MTA1NDU4OTU3NjQwNzk1Njc5fSIsInMiOiJiMTA2MzFhZmZmYTA4Yzk4In0">subscribed</a> to this Developer Newsletter.</p>
]]></content:encoded></item><item><title><![CDATA[Test ITS locally with Axelar Examples]]></title><description><![CDATA[We've been busy developing and launching various tools to support developers in succeeding with Axelar.

We're thrilled that the axelar-examples repository now supports the Interchain Token Service (ITS) for local and testnet testing. This repository...]]></description><link>https://blog.axelar.dev/test-its-locally-with-axelar-examples</link><guid isPermaLink="true">https://blog.axelar.dev/test-its-locally-with-axelar-examples</guid><category><![CDATA[Blockchain]]></category><category><![CDATA[Smart Contracts]]></category><category><![CDATA[React]]></category><category><![CDATA[Frontend Development]]></category><category><![CDATA[Web3]]></category><category><![CDATA[axelar]]></category><category><![CDATA[hardhat]]></category><category><![CDATA[Next.js]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[NFT]]></category><dc:creator><![CDATA[Idris Olubisi]]></dc:creator><pubDate>Mon, 08 Apr 2024 15:51:49 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1712156296053/43281342-e2ea-4cb8-965c-ef00eadf9086.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>We've been busy developing and launching various tools to support developers in succeeding with Axelar.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712156700723/ce63ede9-d950-4e41-af62-503ac1d1b38c.png" alt class="image--center mx-auto" /></p>
<p>We're thrilled that the <a target="_blank" href="https://github.com/axelarnetwork/axelar-examples"><code>axelar-examples</code> repository</a> now supports the <a target="_blank" href="https://github.com/axelarnetwork/interchain-token-service">Interchain Token Service (ITS)</a> for local and testnet testing. This repository is a comprehensive collection of cross-chain DApps and smart contracts examples that utilize the <a target="_blank" href="https://axelar.network/">Axelar protocol</a>. This update allows developers to locally test the Interchain Token Service features with their new or custom tokens.</p>
<h2 id="heading-how-it-works">How it works</h2>
<p>To begin, you'll need to clone the <code>axelar-examples</code> repository to your local machine and follow the instructions in the <a target="_blank" href="https://github.com/axelarnetwork/axelar-examples/blob/main/README.md">README</a>. We've configured five different networks — Ethereum, Avalanche, Moonbeam, Fantom, and Polygon — for testing, so you should be all set.</p>
<h2 id="heading-features">Features</h2>
<p>Some of the ITS examples in the <code>examples</code> folder include:</p>
<ul>
<li><p><a target="_blank" href="https://github.com/axelarnetwork/axelar-examples/tree/main/examples/evm/its-custom-token">Custom Token Example:</a> This example demonstrates how to create a custom interchain token with ITS.</p>
</li>
<li><p><a target="_blank" href="https://github.com/axelarnetwork/axelar-examples/tree/main/examples/evm/its-canonical-token">Canonical Token Example</a>: This example demonstrates how to implement a canonical token using the Lock/Unlock token manager.</p>
</li>
<li><p><a target="_blank" href="https://github.com/axelarnetwork/axelar-examples/tree/main/examples/evm/its-interchain-token">New Interchain Token Example</a>: This example demonstrates how to deploy and send interchain tokens connected across EVM chains.</p>
</li>
<li><p><a target="_blank" href="https://github.com/axelarnetwork/axelar-examples/tree/main/examples/evm/its-executable">Interchain Token Executable Example</a>: This example demonstrates how to relay a message alongside a token from a source chain to a destination chain through the Interchain Token Service.</p>
</li>
</ul>
<h2 id="heading-whats-next">What's next</h2>
<ul>
<li>Check out some of the other examples in the <code>axelar-examples</code> repository, such as the ones in the <code>example</code> and <code>example-web</code> folders. You'll find comprehensive documentation and code examples to kickstart your projects.</li>
</ul>
<h2 id="heading-get-help">Get help</h2>
<p>If you have any questions or concerns, open an issue in our <a target="_blank" href="https://github.com/axelarnetwork/support"><strong>support repository</strong></a>. We're here to help.</p>
]]></content:encoded></item><item><title><![CDATA[Interchain Unit Tests with Axelar Local Dev]]></title><description><![CDATA[Testing your application is critical before going to production, especially in Web3. Axelar Local Dev allows you to simulate interchain transactions on the Axelar Gateway right on your local machine. This provides a Ganache-like testing experience be...]]></description><link>https://blog.axelar.dev/interchain-unit-tests-with-axelar-local-dev</link><guid isPermaLink="true">https://blog.axelar.dev/interchain-unit-tests-with-axelar-local-dev</guid><category><![CDATA[axelar]]></category><category><![CDATA[hardhat]]></category><category><![CDATA[Web3]]></category><category><![CDATA[unit testing]]></category><category><![CDATA[Smart Contracts]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Solidity]]></category><dc:creator><![CDATA[Ben Weinberg]]></dc:creator><pubDate>Wed, 03 Apr 2024 19:58:42 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1712161234141/a1503498-3651-45f7-a6c3-ad006b5f7700.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Testing your application is critical before going to production, especially in Web3. <a target="_blank" href="https://www.npmjs.com/package/@axelar-network/axelar-local-dev">Axelar Local Dev</a> allows you to simulate interchain transactions on the Axelar Gateway right on your local machine. This provides a Ganache-like testing experience before officially migrating to testnet.</p>
<p>The following examples are configured for <a target="_blank" href="https://hardhat.org/hardhat-runner/docs/getting-started#overview">Hardhat</a> based the <a target="_blank" href="https://github.com/axelarnetwork/axelar-examples"><code>axelar-examples</code> repo</a>. Feel free to replicate some of these tests in your own interchain applications.</p>
<h2 id="heading-run-the-tests"><strong>Run the tests</strong></h2>
<p>Axelar Local Dev contains tests for the <a target="_blank" href="https://github.com/axelarnetwork/axelar-examples/tree/main/examples/evm/call-contract">Call Contract</a>, <a target="_blank" href="https://github.com/axelarnetwork/axelar-examples/tree/main/examples/evm/call-contract-with-token">Call Contract With Token</a>, and <a target="_blank" href="https://github.com/axelarnetwork/axelar-examples/tree/main/examples/evm/nft-linker">NFT Linker</a> examples. Make sure you are in the <code>evm</code> directory before running the <code>npx hardhat test</code> command for each example you want to test.</p>
<p>For example, to run the NFT Linker example:</p>
<pre><code class="lang-bash">npx hardhat <span class="hljs-built_in">test</span> nft-linker/tests/NftLinker.test.js
</code></pre>
<h2 id="heading-testing-interchain-contracts"><strong>Testing interchain contracts</strong></h2>
<p>There are a few things to keep in mind when testing contracts with cross-chain functionality:</p>
<ul>
<li><p>Make sure that you have a local network running for each chain. You can create a new local network with the <code>createNetwork</code> command on Axelar Local Dev.</p>
</li>
<li><p>Interchain transactions are triggered with the <code>relay()</code> function. The logic you are testing on the destination chain will not execute until the transaction is relayed.</p>
</li>
</ul>
<h2 id="heading-whats-next"><strong>What's next</strong></h2>
<ul>
<li>Check out the <a target="_blank" href="https://blog.axelar.dev/foundry-axelar-gmp-example-now-supports-axelar-local-cross-chain-development">Foundry Axelar GMP integration</a> with Axelar Local Dev.</li>
</ul>
<h2 id="heading-get-support"><strong>Get support</strong></h2>
<p>If you have any questions or concerns, open an issue in our <a target="_blank" href="https://github.com/axelarnetwork/support"><strong>support repository</strong></a>. We're here to help.</p>
]]></content:encoded></item></channel></rss>