diff --git a/.gitmodules b/.gitmodules index 690924b..b965426 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,12 @@ [submodule "lib/openzeppelin-contracts"] path = lib/openzeppelin-contracts url = https://github.com/OpenZeppelin/openzeppelin-contracts +[submodule "lib/devtools"] + path = lib/devtools + url = https://github.com/layerzero-labs/devtools +[submodule "lib/LayerZero-v2"] + path = lib/LayerZero-v2 + url = https://github.com/layerzero-labs/LayerZero-v2 +[submodule "lib/solidity-bytes-utils"] + path = lib/solidity-bytes-utils + url = https://github.com/GNSPS/solidity-bytes-utils.git diff --git a/foundry.lock b/foundry.lock index 64e2e73..bc8dd9b 100644 --- a/foundry.lock +++ b/foundry.lock @@ -1,4 +1,10 @@ { + "lib/LayerZero-v2": { + "rev": "9c741e7f9790639537b1710a203bcdfd73b0b9ac" + }, + "lib/devtools": { + "rev": "128b697838f4b0fd53ae748093fd66cc409ae5c4" + }, "lib/forge-std": { "tag": { "name": "v1.14.0", diff --git a/foundry.toml b/foundry.toml index ee49283..21daf7f 100644 --- a/foundry.toml +++ b/foundry.toml @@ -7,4 +7,13 @@ evm_version = "cancun" optimizer = true optimizer_runs = 200 +remappings = [ + '@layerzerolabs/oft-evm/=lib/devtools/packages/oft-evm/', + '@layerzerolabs/oapp-evm/=lib/devtools/packages/oapp-evm/', + '@layerzerolabs/lz-evm-protocol-v2/=lib/LayerZero-v2/packages/layerzero-v2/evm/protocol/', + '@layerzerolabs/lz-evm-messagelib-v2/=lib/LayerZero-v2/packages/layerzero-v2/evm/messagelib/', + '@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/', + 'solidity-bytes-utils/=lib/solidity-bytes-utils/', +] + # See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options diff --git a/lib/LayerZero-v2 b/lib/LayerZero-v2 new file mode 160000 index 0000000..9c741e7 --- /dev/null +++ b/lib/LayerZero-v2 @@ -0,0 +1 @@ +Subproject commit 9c741e7f9790639537b1710a203bcdfd73b0b9ac diff --git a/lib/devtools b/lib/devtools new file mode 160000 index 0000000..128b697 --- /dev/null +++ b/lib/devtools @@ -0,0 +1 @@ +Subproject commit 128b697838f4b0fd53ae748093fd66cc409ae5c4 diff --git a/lib/solidity-bytes-utils b/lib/solidity-bytes-utils new file mode 160000 index 0000000..fc50245 --- /dev/null +++ b/lib/solidity-bytes-utils @@ -0,0 +1 @@ +Subproject commit fc502455bb2a7e26a743378df042612dd50d1eb9 diff --git a/src/OpenGradientOFT.sol b/src/OpenGradientOFT.sol new file mode 100644 index 0000000..6ca84ca --- /dev/null +++ b/src/OpenGradientOFT.sol @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; +import {OFT} from "@layerzerolabs/oft-evm/contracts/OFT.sol"; + +/** + * @title OpenGradient OFT + * @dev BSC-side omnichain representation of the canonical OpenGradient token on Base Sepolia. + * Supply should begin at zero on satellite chains and expand/contract through LayerZero sends. + */ +contract OpenGradientOFT is OFT { + string private constant NAME = "OpenGradient"; + string private constant SYMBOL = "OPG"; + + constructor(address _lzEndpoint, address _delegate) OFT(NAME, SYMBOL, _lzEndpoint, _delegate) Ownable(_delegate) {} +} diff --git a/src/OpenGradientOFTAdapter.sol b/src/OpenGradientOFTAdapter.sol new file mode 100644 index 0000000..89aef6a --- /dev/null +++ b/src/OpenGradientOFTAdapter.sol @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; +import {OFTAdapter} from "@layerzerolabs/oft-evm/contracts/OFTAdapter.sol"; + +/** + * @title OpenGradient OFT Adapter + * @dev LayerZero lockbox adapter for the canonical OpenGradient ERC20 on Base Sepolia. + * + * @dev For existing ERC20 tokens, this can be used to convert the token to crosschain compatibility. + * @dev WARNING: ONLY 1 of these should exist for a given global mesh, + * unless you make a NON-default implementation of OFT and needs to be done very carefully. + * @dev WARNING: The default OFTAdapter implementation assumes LOSSLESS transfers, ie. 1 token in, 1 token out. + * IF the 'innerToken' applies something like a transfer fee, the default will NOT work... + * a pre/post balance check will need to be done to calculate the amountSentLD/amountReceivedLD. + */ +contract OpenGradientOFTAdapter is OFTAdapter { + constructor(address _token, address _lzEndpoint, address _delegate) + OFTAdapter(_token, _lzEndpoint, _delegate) + Ownable(_delegate) + {} +}