diff --git a/audit/Mobland.pdf b/audit/Mobland.pdf new file mode 100644 index 0000000..722baaf Binary files /dev/null and b/audit/Mobland.pdf differ diff --git a/audit/README.md b/audit/README.md new file mode 100644 index 0000000..124f6c8 --- /dev/null +++ b/audit/README.md @@ -0,0 +1,49 @@ +# Audit Report Summary + +This repository contains the code audited by EtherAuthority, specifically the commit at https://github.com/superpowerlabs/in-game-assets/tree/b17e7203ab2853d7dad037b7f48257fef9932b43. The full audit report can be found [here](https://etherauthority.io/mobland-protocol-smart-contract-audit/), and a PDF version is also available in this folder. + +We appreciate the professionalism and thoroughness of the audit conducted by EtherAuthority. However, we would like to address some of the issues mentioned in the report. + +## Deposit ID Override Concern: GamePool.sol: \_depositFT() + +This issue is not a vulnerability. The depositId is generated off-chain by the Game App and passed to the functions depositBud and depositSeed along with a signature to guarantee the correctness of the parameters passed to the contract. + +For example, the depositSeed function is shown below: + +```solidity +function depositSeed( + uint256 amount, + uint64 depositId, + uint256 randomNonce, + bytes calldata signature0 +) external override { + if (!isSignedByAValidator(0, 2, hashDeposit(_msgSender(), amount, depositId, randomNonce), signature0)) + revert invalidPrimarySignature(); + _saveSignatureAsUsed(signature0); + _depositFT(SEED, amount, depositId, _msgSender()); +} + +``` + +The uniqueness of the depositId is ensured by the Game dApp, which also generates the signature, and by the fact that the signature is saved as used with \_saveSignatureAsUsed(signature0) and cannot be used again. + +Since the smart contract must trust the signature accompanying the request, checking for the uniqueness of the depositId would only waste gas. + +## Infinite Loops Possibility: NftFactory.sol: newSale() + +There is no risk of infinite loops. The factory was designed as a generic factory for flexibility, but it was only used to sell two NFTs—Turf and Farm tokens—using two payment tokens—SEED and USDC. + +As a result, we did not check the gasleft() in the loop to ensure the transaction would not run out of gas. + +## Solhint Warnings + +We initially used Solhint to check for lint warnings and errors. After the audit report, we integrated it into the pre-commit process, allowing commits only if Solhint returns no warnings and all tests pass. In both scenarios, we did not encounter any of the issues mentioned in the report. + +Many of these issues appear to be false positives, as they involve errors such as: + +``` +NftFactory.sol:3565:64: Error: Parse error: mismatched input '(' +expecting {';', '='} +``` + +A missing `;` would result in a compilation error, not a warning. And we would not be able to deploy the contracts and make the sale. diff --git a/bin/clean-licenses-in-flattened.js b/bin/clean-licenses-in-flattened.js index 846946f..a467ecf 100755 --- a/bin/clean-licenses-in-flattened.js +++ b/bin/clean-licenses-in-flattened.js @@ -2,20 +2,73 @@ const fs = require("fs"); const path = require("path"); +const ethers = require("ethers"); const [, , contract] = process.argv; const fn = path.resolve(__dirname, "../flattened", `${contract}-flattened.sol`); -const flattened = fs.readFileSync(fn, "utf8"); +const flattened = + fs.readFileSync(fn, "utf8") + + ` +// Flattened on ${new Date().toISOString()} +`; -flattened - .replace(/SPDX-License-Identifier/, "LICENSE-ID") - .replace(/SPDX-License-Identifier/g, "License") - .replace(/LICENSE-ID/, "SPDX-License-Identifier"); +function removeAndCompact(contents) { + // Remove single-line comments + const singleLineComments = /\/\/.*$/gm; + contents = contents.replace(singleLineComments, ""); -fs.writeFileSync( - fn, + // Remove multi-line comments + const multiLineComments = /\/\*[\s\S]*?\*\//gm; + contents = contents.replace(multiLineComments, ""); + + // Remove new lines and extra spaces + const newLines = /\s*[\r\n]+\s*/g; + contents = contents.replace(newLines, " "); + + // Remove extra spaces between words + const extraSpaces = / +/g; + contents = contents.replace(extraSpaces, " "); + + // Remove space before and after curly braces + const spacesAroundBraces = /\s*([{}])\s*/g; + contents = contents.replace(spacesAroundBraces, "$1"); + + // Remove space before and after parentheses + const spacesAroundParentheses = /\s*([()])\s*/g; + contents = contents.replace(spacesAroundParentheses, "$1"); + + // Remove space before and after semicolons + const spacesAroundSemicolons = /\s*;\s*/g; + contents = contents.replace(spacesAroundSemicolons, ";"); + + // Remove space before and after commas + const spacesAroundCommas = /\s*,\s*/g; + contents = contents.replace(spacesAroundCommas, ","); + return contents.trim(); +} + +const hash = ethers.utils.id(removeAndCompact(flattened)).substring(2, 10); + +const nfn = fn.replace(/flattened\.sol$/, `${hash}.sol`); +if (fs.existsSync(nfn)) { + const prev = fs.readFileSync(nfn, "utf8").split("\n// Flattened on ")[1].split("\n")[0].split("T")[0]; + console.log(` +An identical version of ${contract} has been previously flattened on ${prev}. + +`); +} else { flattened .replace(/SPDX-License-Identifier/, "LICENSE-ID") .replace(/SPDX-License-Identifier/g, "License") - .replace(/LICENSE-ID/, "SPDX-License-Identifier") -); + .replace(/LICENSE-ID/, "SPDX-License-Identifier"); + + fs.writeFileSync( + fn.replace(/flattened\.sol$/, `${hash}.sol`), + flattened + .replace(/SPDX-License-Identifier/, "LICENSE-ID") + .replace(/SPDX-License-Identifier/g, "License") + .replace(/LICENSE-ID/, "SPDX-License-Identifier") + ); + + fs.unlinkSync(fn); +} diff --git a/contracts/GamePool.sol b/contracts/GamePool.sol index 9aa9139..cfd5385 100644 --- a/contracts/GamePool.sol +++ b/contracts/GamePool.sol @@ -25,30 +25,6 @@ import "./utils/SignableStakes.sol"; contract GamePool is IGamePool, SignableStakes, Constants, UUPSUpgradableTemplate, IAttributablePlayer { using SafeMathUpgradeable for uint256; - event AssetStaked(address from, uint8 tokenType, uint16 tokenId); - event AssetUnstaked(address to, uint8 tokenType, uint16 tokenId); - event WithdrawnFT(uint8 tokenType, uint256 amount, address beneficiary); - - error turfNotERC721(); - error farmNotERC721(); - error seedNotSEED(); - error budNotBUD(); - error turfAlreadyLocked(); - error farmAlreadyLocked(); - error invalidTokenType(); - error invalidPrimarySignature(); - error invalidSecondarySignature(); - error assetNotFound(); - error turfNotLocked(); - error farmNotLocked(); - error signatureAlreadyUsed(); - error invalidRecipient(); - error invalidNFT(); - error harvestingExpired(); - error amountNotAvailable(); - error unsupportedNFT(); - error depositAlreadyExists(); - Conf public conf; mapping(address => User) internal _users; mapping(bytes32 => bool) private _usedSignatures; @@ -427,13 +403,12 @@ contract GamePool is IGamePool, SignableStakes, Constants, UUPSUpgradableTemplat emit Harvested(_msgSender(), amount, opId); } - // THIS IS NOT USED, can we remove it? - // /// @notice Returns true if the signature has been used before - // /// @param signature bytes for the signature - // function isSignatureUsed(bytes calldata signature) external view returns (bool) { - // bytes32 key = bytes32(keccak256(abi.encodePacked(signature))); - // return _usedSignatures[key]; - // } + /// @notice Returns true if the signature has been used before + /// @param signature bytes for the signature + function isSignatureUsed(bytes calldata signature) external view returns (bool) { + bytes32 key = bytes32(keccak256(abi.encodePacked(signature))); + return _usedSignatures[key]; + } /// @notice Withdraws an amount of funds in SEEDS or BUDS, or all of them if amount is 0 /// @dev The token emits a Transfer event with the pool as the sender, diff --git a/contracts/SuperpowerNFT.sol b/contracts/SuperpowerNFT.sol index 00fdf92..29bf6cb 100644 --- a/contracts/SuperpowerNFT.sol +++ b/contracts/SuperpowerNFT.sol @@ -110,4 +110,6 @@ abstract contract SuperpowerNFT is ISuperpowerNFT, SuperpowerNFTBase { function nextTokenId() external view override returns (uint256) { return _nextTokenId; } + + uint256[50] private __gap; } diff --git a/contracts/SuperpowerNFTBase.sol b/contracts/SuperpowerNFTBase.sol index ce311c3..9894051 100644 --- a/contracts/SuperpowerNFTBase.sol +++ b/contracts/SuperpowerNFTBase.sol @@ -12,7 +12,7 @@ import "@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721Enumer import "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; -import "./wormhole721/Wormhole721Upgradeable.sol"; +import "@ndujalabs/wormhole721/contracts/Wormhole721Upgradeable.sol"; import "@openzeppelin/contracts-upgradeable/utils/introspection/IERC165Upgradeable.sol"; import "./interfaces/IAttributable.sol"; @@ -154,7 +154,6 @@ abstract contract SuperpowerNFTBase is returns (bool) { return - interfaceId == type(IERC5192).interfaceId || interfaceId == type(IAttributable).interfaceId || interfaceId == type(ILockable).interfaceId || super.supportsInterface(interfaceId); @@ -241,7 +240,7 @@ abstract contract SuperpowerNFTBase is revert LockerNotApproved(); } _lockedBy[tokenId] = _msgSender(); - emit Locked(tokenId); + emit Locked(tokenId, true); } function unlock(uint256 tokenId) external override onlyLocker { @@ -250,7 +249,7 @@ abstract contract SuperpowerNFTBase is revert WrongLocker(); } delete _lockedBy[tokenId]; - emit Unlocked(tokenId); + emit Locked(tokenId, false); } // emergency function in case a compromised locker is removed @@ -314,7 +313,7 @@ abstract contract SuperpowerNFTBase is uint16 recipientChain, bytes32 recipient, uint32 nonce - ) public payable override returns (uint64 sequence) { + ) public payable override whenNotPaused returns (uint64 sequence) { if (locked(tokenID)) revert LockedAsset(); return super.wormholeTransfer(tokenID, recipientChain, recipient, nonce); } diff --git a/contracts/interfaces/IERC5192.sol b/contracts/interfaces/IERC5192.sol deleted file mode 100644 index 7a4f2d4..0000000 --- a/contracts/interfaces/IERC5192.sol +++ /dev/null @@ -1,23 +0,0 @@ -// SPDX-License-Identifier: CC0-1.0 -pragma solidity ^0.8.0; - -// Author: Tim Daubenschütz (tim@daubenschuetz.de) -// Repo: https://github.com/attestate/ERC5192/blob/main/src/IERC5192.sol - -interface IERC5192 { - /// @notice Emitted when the locking status is changed to locked. - /// @dev If a token is minted and the status is locked, this event should be emitted. - /// @param tokenId The identifier for a token. - event Locked(uint256 tokenId); - - /// @notice Emitted when the locking status is changed to unlocked. - /// @dev If a token is minted and the status is unlocked, this event should be emitted. - /// @param tokenId The identifier for a token. - event Unlocked(uint256 tokenId); - - /// @notice Returns the locking status of an Soulbound Token - /// @dev SBTs assigned to zero address are considered invalid, and queries - /// about them do throw. - /// @param tokenId The identifier for an SBT. - function locked(uint256 tokenId) external view returns (bool); -} diff --git a/contracts/interfaces/IERC721DefaultLockable.sol b/contracts/interfaces/IERC721DefaultLockable.sol new file mode 100644 index 0000000..2dc24c5 --- /dev/null +++ b/contracts/interfaces/IERC721DefaultLockable.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: CC0-1.0 +pragma solidity ^0.8.0; + +interface IERC721DefaultLockable { + // Must be emitted one time, when the contract is deployed, + // defining the default status of any token that will be minted + event DefaultLocked(bool locked); + + // Must be emitted any time the status changes + event Locked(uint256 indexed tokenId, bool locked); + + // Returns the status of the token. + // It should revert if the token does not exist. + function locked(uint256 tokenId) external view returns (bool); +} diff --git a/contracts/interfaces/IGamePool.sol b/contracts/interfaces/IGamePool.sol index f99b0c2..ee86cee 100644 --- a/contracts/interfaces/IGamePool.sol +++ b/contracts/interfaces/IGamePool.sol @@ -11,6 +11,30 @@ interface IGamePool is IUserSimplified { event Harvested(address user, uint256 amount, uint64 opId); event NewDepositAndPay(uint64 depositId, address user, address otherUser); event NewDeposit(uint64 depositId, address user, uint8 tokenType, uint256 amount); + event AssetStaked(address from, uint8 tokenType, uint16 tokenId); + event AssetUnstaked(address to, uint8 tokenType, uint16 tokenId); + event WithdrawnFT(uint8 tokenType, uint256 amount, address beneficiary); + + error turfNotERC721(); + error farmNotERC721(); + error seedNotSEED(); + error budNotBUD(); + error turfAlreadyLocked(); + error farmAlreadyLocked(); + error invalidTokenType(); + error invalidPrimarySignature(); + error invalidSecondarySignature(); + error assetNotFound(); + error turfNotLocked(); + error farmNotLocked(); + error signatureAlreadyUsed(); + error invalidRecipient(); + error invalidNFT(); + error harvestingExpired(); + error amountNotAvailable(); + error unsupportedNFT(); + error depositAlreadyExists(); + /** @dev to have a quick vision of the TVL */ diff --git a/contracts/interfaces/ILockable.sol b/contracts/interfaces/ILockable.sol index 9786098..8653048 100644 --- a/contracts/interfaces/ILockable.sol +++ b/contracts/interfaces/ILockable.sol @@ -5,10 +5,10 @@ pragma solidity ^0.8.4; // Francesco Sullo // Taken from https://github.com/ndujaLabs/lockable -import "./IERC5192.sol"; +import "./IERC721DefaultLockable.sol"; // ERC165 interface id is 0xd8e4c296 -interface ILockable is IERC5192 { +interface ILockable is IERC721DefaultLockable { event LockerSet(address locker); event LockerRemoved(address locker); event ForcefullyUnlocked(uint256 tokenId); diff --git a/contracts/interfaces/ISuperpowerNFT.sol b/contracts/interfaces/ISuperpowerNFT.sol index 926cfa6..17713bd 100644 --- a/contracts/interfaces/ISuperpowerNFT.sol +++ b/contracts/interfaces/ISuperpowerNFT.sol @@ -4,7 +4,9 @@ pragma solidity 0.8.17; // Authors: Francesco Sullo // (c) Superpower Labs Inc -interface ISuperpowerNFT { +import "./ISuperpowerNFTBase.sol"; + +interface ISuperpowerNFT is ISuperpowerNFTBase { error Forbidden(); error CannotMint(); error InvalidSupply(); diff --git a/contracts/mocks/FarmMock.sol b/contracts/mocks/FarmMock.sol index 0fac881..052f3bf 100644 --- a/contracts/mocks/FarmMock.sol +++ b/contracts/mocks/FarmMock.sol @@ -18,4 +18,8 @@ contract FarmMock { function mintTokens(address to, uint256 amount) external { nft.mint(to, amount); } + + function lockToken(uint256 tokenId) external { + nft.lock(tokenId); + } } diff --git a/contracts/tokens/EventPatch.sol b/contracts/tokens/EventPatch.sol new file mode 100644 index 0000000..af3582a --- /dev/null +++ b/contracts/tokens/EventPatch.sol @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +// Authors: Francesco Sullo +// (c) Superpower Labs Inc. + +import "../SuperpowerNFT.sol"; + +//import "hardhat/console.sol"; +// Intermediate contract to fix a typo in the Locked and Unlocked events + +contract EventPatch is SuperpowerNFT { + // Unfortunately, there was a typo in the parameter "tokenId" of the events + // Locked and Unlocked, and it was spelled as "tokendId". + // This patch fixes the typo and emits new events with the correct parameter name. + + error DefaultLockedAlreadyEmitted(); + error NewLockedAlreadyEmitted(); + + bool public defaultLockedEmitted; + uint256 public lastCheckedId; + bool public allNewLockedEmitted; + + function emitNewLockedEvent() public { + if (!defaultLockedEmitted) { + emit DefaultLocked(true); + defaultLockedEmitted = true; + } + if (allNewLockedEmitted) { + revert NewLockedAlreadyEmitted(); + } + uint256 fromId = lastCheckedId + 1; + for (uint256 i = fromId; i < _nextTokenId; i++) { + if (locked(i)) { + emit Locked(i, true); + } + if (gasleft() < 30000 || i == totalSupply()) { + lastCheckedId = i; + if (i == totalSupply()) { + allNewLockedEmitted = true; + } + break; + } + } + } + + uint256[49] private __gap; +} diff --git a/contracts/tokens/Farm.sol b/contracts/tokens/Farm.sol index bfa4fbd..035de0a 100644 --- a/contracts/tokens/Farm.sol +++ b/contracts/tokens/Farm.sol @@ -4,10 +4,9 @@ pragma solidity 0.8.17; // Authors: Francesco Sullo // (c) Superpower Labs Inc. -//import "./FarmTokenBase.sol"; -import "../SuperpowerNFT.sol"; +import "./EventPatch.sol"; -contract Farm is SuperpowerNFT { +contract Farm is EventPatch { function initialize(string memory tokenUri) public initializer onlyProxy { __SuperpowerNFTBase_init("MOBLAND Farm", "mFARM", tokenUri); } diff --git a/contracts/tokens/FarmBridged.sol b/contracts/tokens/FarmBridged.sol index 2c3e72b..f09d54c 100644 --- a/contracts/tokens/FarmBridged.sol +++ b/contracts/tokens/FarmBridged.sol @@ -9,5 +9,6 @@ import "../SuperpowerNFTBase.sol"; contract FarmBridged is SuperpowerNFTBase { function initialize(string memory tokenUri) public initializer onlyProxy { __SuperpowerNFTBase_init("MOBLAND Farm", "mFARM", tokenUri); + emit DefaultLocked(false); } } diff --git a/contracts/tokens/Turf.sol b/contracts/tokens/Turf.sol index 64893e6..93c3045 100644 --- a/contracts/tokens/Turf.sol +++ b/contracts/tokens/Turf.sol @@ -4,9 +4,9 @@ pragma solidity 0.8.17; // Authors: Francesco Sullo // (c) Superpower Labs Inc. -import "../SuperpowerNFT.sol"; +import "./EventPatch.sol"; -contract Turf is SuperpowerNFT { +contract Turf is EventPatch { function initialize(string memory tokenUri) public initializer onlyProxy { __SuperpowerNFTBase_init("MOBLAND Turf", "mTURF", tokenUri); } diff --git a/contracts/tokens/TurfBridged.sol b/contracts/tokens/TurfBridged.sol index 31e1b9e..360736e 100644 --- a/contracts/tokens/TurfBridged.sol +++ b/contracts/tokens/TurfBridged.sol @@ -9,5 +9,6 @@ import "../SuperpowerNFTBase.sol"; contract TurfBridged is SuperpowerNFTBase { function initialize(string memory tokenUri) public initializer onlyProxy { __SuperpowerNFTBase_init("MOBLAND Turf", "mTURF", tokenUri); + emit DefaultLocked(false); } } diff --git a/contracts/wormhole-tunnel/README.md b/contracts/wormhole-tunnel/README.md deleted file mode 100644 index 24e7b42..0000000 --- a/contracts/wormhole-tunnel/README.md +++ /dev/null @@ -1,3 +0,0 @@ -Original code at https://github.com/ndujaLabs/wormhole-tunnel -More info and testing for this code is in the original repo. -The code is here because has not been audited yet. diff --git a/contracts/wormhole-tunnel/WormholeCommon.sol b/contracts/wormhole-tunnel/WormholeCommon.sol deleted file mode 100644 index 5198099..0000000 --- a/contracts/wormhole-tunnel/WormholeCommon.sol +++ /dev/null @@ -1,136 +0,0 @@ -// SPDX-License-Identifier: Apache2 -pragma solidity ^0.8.0; - -import "./interfaces/IWormhole.sol"; -import "./libraries/BytesLib.sol"; - -contract WormholeCommon { - using BytesLib for bytes; - struct WTransfer { - // PayloadID uint8 = 1 - // TokenID of the token, if an NFT; amount if a transfer; encoded uint for something else - uint256 payload; - // Address of the recipient. Left-zero-padded if shorter than 32 bytes - bytes32 to; - // Chain ID of the recipient - uint16 toChain; - } - - struct State { - // Wormhole bridge contract address and chainId - address payable wormhole; - uint16 chainId; - // Mapping of consumed token transfers - mapping(bytes32 => bool) completedTransfers; - // Mapping of contracts on other chains - mapping(uint16 => bytes32) contractsByChainId; - } - - // solhint-disable-next-line state-visibility - State _wormholeState; - - function isTransferCompleted(bytes32 hash) public view returns (bool) { - return _wormholeState.completedTransfers[hash]; - } - - function contractByChainId(uint16 chainId_) public view returns (bytes32) { - return _wormholeState.contractsByChainId[chainId_]; - } - - function wormhole() public view returns (IWormhole) { - return IWormhole(_wormholeState.wormhole); - } - - function chainId() public view returns (uint16) { - return _wormholeState.chainId; - } - - function _setWormhole(address wh) internal { - _wormholeState.wormhole = payable(wh); - } - - function _setChainId(uint16 chainId_) internal { - _wormholeState.chainId = chainId_; - } - - function _setTransferCompleted(bytes32 hash) internal { - _wormholeState.completedTransfers[hash] = true; - } - - function _setContract(uint16 chainId_, bytes32 contractExtendedAddress) internal { - _wormholeState.contractsByChainId[chainId_] = contractExtendedAddress; - } - - function _wormholeCompleteTransfer(bytes memory encodedVm) internal returns (address to, uint256 payload) { - (IWormhole.VM memory vm, bool valid, string memory reason) = wormhole().parseAndVerifyVM(encodedVm); - - require(valid, reason); - - require(_verifyContractVM(vm), "invalid emitter"); - - WTransfer memory wTransfer = _parseTransfer(vm.payload); - - require(!isTransferCompleted(vm.hash), "transfer already completed"); - _setTransferCompleted(vm.hash); - - require(wTransfer.toChain == chainId(), "invalid target chain"); - - // transfer bridged NFT to recipient - address transferRecipient = address(uint160(uint256(wTransfer.to))); - - return (transferRecipient, wTransfer.payload); - } - - function _wormholeTransferWithValue( - uint256 payload, - uint16 recipientChain, - bytes32 recipient, - uint32 nonce, - uint256 value - ) internal returns (uint64 sequence) { - require(contractByChainId(recipientChain) != 0, "recipientChain not allowed"); - sequence = _logTransfer(WTransfer({payload: payload, to: recipient, toChain: recipientChain}), value, nonce); - return sequence; - } - - function _logTransfer( - WTransfer memory wTransfer, - uint256 callValue, - uint32 nonce - ) internal returns (uint64 sequence) { - bytes memory encoded = _encodeTransfer(wTransfer); - sequence = wormhole().publishMessage{value: callValue}(nonce, encoded, 15); - } - - function _verifyContractVM(IWormhole.VM memory vm) internal view returns (bool) { - if (contractByChainId(vm.emitterChainId) == vm.emitterAddress) { - return true; - } - return false; - } - - function _encodeTransfer(WTransfer memory wTransfer) internal pure returns (bytes memory encoded) { - encoded = abi.encodePacked(uint8(1), wTransfer.payload, wTransfer.to, wTransfer.toChain); - } - - function _parseTransfer(bytes memory encoded) internal pure returns (WTransfer memory wTransfer) { - uint256 index = 0; - - uint8 payloadId = encoded.toUint8(index); - index += 1; - - require(payloadId == 1, "invalid WTransfer"); - - wTransfer.payload = encoded.toUint256(index); - index += 32; - - wTransfer.to = encoded.toBytes32(index); - index += 32; - - wTransfer.toChain = encoded.toUint16(index); - index += 2; - - require(encoded.length == index, "invalid WTransfer"); - return wTransfer; - } -} diff --git a/contracts/wormhole-tunnel/WormholeTunnel.sol b/contracts/wormhole-tunnel/WormholeTunnel.sol deleted file mode 100644 index d585718..0000000 --- a/contracts/wormhole-tunnel/WormholeTunnel.sol +++ /dev/null @@ -1,58 +0,0 @@ -// SPDX-License-Identifier: Apache2 -pragma solidity ^0.8.0; - -import "@openzeppelin/contracts/security/Pausable.sol"; -import "@openzeppelin/contracts/access/Ownable.sol"; -import "@openzeppelin/contracts/utils/introspection/ERC165.sol"; - -import "./interfaces/IWormhole.sol"; -import "./libraries/BytesLib.sol"; -import "./WormholeCommon.sol"; -import "./interfaces/IWormholeTunnel.sol"; - -abstract contract WormholeTunnel is IWormholeTunnel, WormholeCommon, Ownable, Pausable, ERC165 { - using BytesLib for bytes; - - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - // console.log(bytes32(type(IWormholeTunnel).interfaceId)); - return interfaceId == type(IWormholeTunnel).interfaceId || super.supportsInterface(interfaceId); - } - - function getInterfaceId() public view virtual returns (bytes4) { - return type(IWormholeTunnel).interfaceId; - } - - function wormholeInit(uint16 chainId, address wormhole) public override onlyOwner { - _setChainId(chainId); - _setWormhole(wormhole); - } - - function wormholeRegisterContract(uint16 chainId_, bytes32 contractExtendedAddress) public override onlyOwner { - _setContract(chainId_, contractExtendedAddress); - } - - function wormholeGetContract(uint16 chainId) public view override returns (bytes32) { - return contractByChainId(chainId); - } - - /** @dev Examples of implementation for an ERC721: - - function wormholeTransfer( - uint256 payload, - uint16 recipientChain, - bytes32 recipient, - uint32 nonce - ) public payable virtual override whenNotPaused returns (uint64 sequence) { - require(owner(payload) == _msgSender(), "ERC721: transfer caller is not the owner"); - _burn(payload); - return _wormholeTransferWithValue(payload, recipientChain, recipient, nonce, msg.value); - } - - // Complete a transfer from Wormhole - function wormholeCompleteTransfer(bytes memory encodedVm) public virtual override { - (address to, uint256 payload) = _wormholeCompleteTransfer(encodedVm); - _safeMint(to, payload); - } - - */ -} diff --git a/contracts/wormhole-tunnel/WormholeTunnelUpgradeable.sol b/contracts/wormhole-tunnel/WormholeTunnelUpgradeable.sol deleted file mode 100644 index e79d49c..0000000 --- a/contracts/wormhole-tunnel/WormholeTunnelUpgradeable.sol +++ /dev/null @@ -1,75 +0,0 @@ -// SPDX-License-Identifier: Apache2 -pragma solidity ^0.8.0; - -import "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol"; -import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; -import "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol"; -import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; - -import "./interfaces/IWormhole.sol"; -import "./libraries/BytesLib.sol"; -import "./WormholeCommon.sol"; -import "./interfaces/IWormholeTunnel.sol"; - -abstract contract WormholeTunnelUpgradeable is - IWormholeTunnel, - WormholeCommon, - PausableUpgradeable, - OwnableUpgradeable, - UUPSUpgradeable, - ERC165Upgradeable -{ - using BytesLib for bytes; - event ImplementationUpgraded(address newImplementation); - - // solhint-disable-next-line func-name-mixedcase - function __WormholeTunnel_init() internal virtual initializer { - __Ownable_init(); - __Pausable_init(); - __UUPSUpgradeable_init(); - } - - function _authorizeUpgrade(address newImplementation) internal virtual override onlyOwner { - emit ImplementationUpgraded(newImplementation); - } - - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IWormholeTunnel).interfaceId || super.supportsInterface(interfaceId); - } - - function wormholeInit(uint16 chainId, address wormhole) public override onlyOwner { - _setChainId(chainId); - _setWormhole(wormhole); - } - - function wormholeRegisterContract(uint16 chainId_, bytes32 contractExtendedAddress) public override onlyOwner { - _setContract(chainId_, contractExtendedAddress); - } - - function wormholeGetContract(uint16 chainId) public view override returns (bytes32) { - return contractByChainId(chainId); - } - - /** @dev Examples of implementation for an ERC721: - - function wormholeTransfer( - uint256 payload, - uint16 recipientChain, - bytes32 recipient, - uint32 nonce - ) public payable virtual override whenNotPaused returns (uint64 sequence) { - require(owner(payload) == _msgSender(), "ERC721: transfer caller is not the owner"); - _burn(payload); - return _wormholeTransferWithValue(payload, recipientChain, recipient, nonce, msg.value); - } - - // Complete a transfer from Wormhole - function wormholeCompleteTransfer(bytes memory encodedVm) public virtual override { - (address to, uint256 payload) = _wormholeCompleteTransfer(encodedVm); - _safeMint(to, payload); - } - - */ - - uint256[50] private __gap; -} diff --git a/contracts/wormhole-tunnel/interfaces/IWormhole.sol b/contracts/wormhole-tunnel/interfaces/IWormhole.sol deleted file mode 100644 index 89c6871..0000000 --- a/contracts/wormhole-tunnel/interfaces/IWormhole.sol +++ /dev/null @@ -1,51 +0,0 @@ -// SPDX-License-Identifier: Apache2 -pragma solidity ^0.8.0; - -import "./IWormholeStructs.sol"; - -interface IWormhole is IWormholeStructs { - event LogMessagePublished(address indexed sender, uint64 sequence, uint32 nonce, bytes payload, uint8 consistencyLevel); - - function publishMessage( - uint32 nonce, - bytes memory payload, - uint8 consistencyLevel - ) external payable returns (uint64 sequence); - - function parseAndVerifyVM(bytes calldata encodedVM) - external - view - returns ( - IWormholeStructs.VM memory vm, - bool valid, - string memory reason - ); - - function verifyVM(IWormholeStructs.VM memory vm) external view returns (bool valid, string memory reason); - - function verifySignatures( - bytes32 hash, - IWormholeStructs.Signature[] memory signatures, - IWormholeStructs.GuardianSet memory guardianSet - ) external pure returns (bool valid, string memory reason); - - function parseVM(bytes memory encodedVM) external pure returns (IWormholeStructs.VM memory vm); - - function getGuardianSet(uint32 index) external view returns (IWormholeStructs.GuardianSet memory); - - function getCurrentGuardianSetIndex() external view returns (uint32); - - function getGuardianSetExpiry() external view returns (uint32); - - function governanceActionIsConsumed(bytes32 hash) external view returns (bool); - - function isInitialized(address impl) external view returns (bool); - - function chainId() external view returns (uint16); - - function governanceChainId() external view returns (uint16); - - function governanceContract() external view returns (bytes32); - - function messageFee() external view returns (uint256); -} diff --git a/contracts/wormhole-tunnel/interfaces/IWormholeStructs.sol b/contracts/wormhole-tunnel/interfaces/IWormholeStructs.sol deleted file mode 100644 index 00ca4f3..0000000 --- a/contracts/wormhole-tunnel/interfaces/IWormholeStructs.sol +++ /dev/null @@ -1,36 +0,0 @@ -// SPDX-License-Identifier: Apache2 -pragma solidity ^0.8.0; - -interface IWormholeStructs { - struct Provider { - uint16 chainId; - uint16 governanceChainId; - bytes32 governanceContract; - } - - struct GuardianSet { - address[] keys; - uint32 expirationTime; - } - - struct Signature { - bytes32 r; - bytes32 s; - uint8 v; - uint8 guardianIndex; - } - - struct VM { - uint8 version; - uint32 timestamp; - uint32 nonce; - uint16 emitterChainId; - bytes32 emitterAddress; - uint64 sequence; - uint8 consistencyLevel; - bytes payload; - uint32 guardianSetIndex; - Signature[] signatures; - bytes32 hash; - } -} diff --git a/contracts/wormhole-tunnel/interfaces/IWormholeTunnel.sol b/contracts/wormhole-tunnel/interfaces/IWormholeTunnel.sol deleted file mode 100644 index 9540ba1..0000000 --- a/contracts/wormhole-tunnel/interfaces/IWormholeTunnel.sol +++ /dev/null @@ -1,21 +0,0 @@ -// SPDX-License-Identifier: Apache2 -pragma solidity ^0.8.0; - -/// ERC165 interfaceId is 0x647bffff -/* is IERC165 */ -interface IWormholeTunnel { - function wormholeInit(uint16 chainId, address wormhole) external; - - function wormholeRegisterContract(uint16 chainId, bytes32 contractByChainId) external; - - function wormholeGetContract(uint16 chainId) external view returns (bytes32); - - function wormholeTransfer( - uint256 payload, - uint16 recipientChain, - bytes32 recipient, - uint32 nonce - ) external payable returns (uint64 sequence); - - function wormholeCompleteTransfer(bytes memory encodedVm) external; -} diff --git a/contracts/wormhole-tunnel/libraries/BytesLib.sol b/contracts/wormhole-tunnel/libraries/BytesLib.sol deleted file mode 100644 index 1801bfa..0000000 --- a/contracts/wormhole-tunnel/libraries/BytesLib.sol +++ /dev/null @@ -1,502 +0,0 @@ -// SPDX-License-Identifier: Unlicense -/* - * @title Solidity Bytes Arrays Utils - * @author Gonçalo Sá - * - * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity. - * The library lets you concatenate, slice and type cast bytes arrays both in memory and storage. - */ -pragma solidity >=0.8.0 <0.9.0; - -library BytesLib { - function concat(bytes memory _preBytes, bytes memory _postBytes) internal pure returns (bytes memory) { - bytes memory tempBytes; - - // solhint-disable-next-line no-inline-assembly - assembly { - // Get a location of some free memory and store it in tempBytes as - // Solidity does for memory variables. - tempBytes := mload(0x40) - - // Store the length of the first bytes array at the beginning of - // the memory for tempBytes. - let length := mload(_preBytes) - mstore(tempBytes, length) - - // Maintain a memory counter for the current write location in the - // temp bytes array by adding the 32 bytes for the array length to - // the starting location. - let mc := add(tempBytes, 0x20) - // Stop copying when the memory counter reaches the length of the - // first bytes array. - let end := add(mc, length) - - for { - // Initialize a copy counter to the start of the _preBytes data, - // 32 bytes into its memory. - let cc := add(_preBytes, 0x20) - } lt(mc, end) { - // Increase both counters by 32 bytes each iteration. - mc := add(mc, 0x20) - cc := add(cc, 0x20) - } { - // Write the _preBytes data into the tempBytes memory 32 bytes - // at a time. - mstore(mc, mload(cc)) - } - - // Add the length of _postBytes to the current length of tempBytes - // and store it as the new length in the first 32 bytes of the - // tempBytes memory. - length := mload(_postBytes) - mstore(tempBytes, add(length, mload(tempBytes))) - - // Move the memory counter back from a multiple of 0x20 to the - // actual end of the _preBytes data. - mc := end - // Stop copying when the memory counter reaches the new combined - // length of the arrays. - end := add(mc, length) - - for { - let cc := add(_postBytes, 0x20) - } lt(mc, end) { - mc := add(mc, 0x20) - cc := add(cc, 0x20) - } { - mstore(mc, mload(cc)) - } - - // Update the free-memory pointer by padding our last write location - // to 32 bytes: add 31 bytes to the end of tempBytes to move to the - // next 32 byte block, then round down to the nearest multiple of - // 32. If the sum of the length of the two arrays is zero then add - // one before rounding down to leave a blank 32 bytes (the length block with 0). - mstore( - 0x40, - and( - add(add(end, iszero(add(length, mload(_preBytes)))), 31), - not(31) // Round down to the nearest 32 bytes. - ) - ) - } - - return tempBytes; - } - - function concatStorage(bytes storage _preBytes, bytes memory _postBytes) internal { - // solhint-disable-next-line no-inline-assembly - assembly { - // Read the first 32 bytes of _preBytes storage, which is the length - // of the array. (We don't need to use the offset into the slot - // because arrays use the entire slot.) - let fslot := sload(_preBytes.slot) - // Arrays of 31 bytes or less have an even value in their slot, - // while longer arrays have an odd value. The actual length is - // the slot divided by two for odd values, and the lowest order - // byte divided by two for even values. - // If the slot is even, bitwise and the slot with 255 and divide by - // two to get the length. If the slot is odd, bitwise and the slot - // with -1 and divide by two. - let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2) - let mlength := mload(_postBytes) - let newlength := add(slength, mlength) - // slength can contain both the length and contents of the array - // if length < 32 bytes so let's prepare for that - // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage - switch add(lt(slength, 32), lt(newlength, 32)) - case 2 { - // Since the new array still fits in the slot, we just need to - // update the contents of the slot. - // uint256(bytes_storage) = uint256(bytes_storage) + uint256(bytes_memory) + new_length - sstore( - _preBytes.slot, - // all the modifications to the slot are inside this - // next block - add( - // we can just add to the slot contents because the - // bytes we want to change are the LSBs - fslot, - add( - mul( - div( - // load the bytes from memory - mload(add(_postBytes, 0x20)), - // zero all bytes to the right - exp(0x100, sub(32, mlength)) - ), - // and now shift left the number of bytes to - // leave space for the length in the slot - exp(0x100, sub(32, newlength)) - ), - // increase length by the double of the memory - // bytes length - mul(mlength, 2) - ) - ) - ) - } - case 1 { - // The stored value fits in the slot, but the combined value - // will exceed it. - // get the keccak hash to get the contents of the array - mstore(0x0, _preBytes.slot) - let sc := add(keccak256(0x0, 0x20), div(slength, 32)) - - // save new length - sstore(_preBytes.slot, add(mul(newlength, 2), 1)) - - // The contents of the _postBytes array start 32 bytes into - // the structure. Our first read should obtain the `submod` - // bytes that can fit into the unused space in the last word - // of the stored array. To get this, we read 32 bytes starting - // from `submod`, so the data we read overlaps with the array - // contents by `submod` bytes. Masking the lowest-order - // `submod` bytes allows us to add that value directly to the - // stored value. - - let submod := sub(32, slength) - let mc := add(_postBytes, submod) - let end := add(_postBytes, mlength) - let mask := sub(exp(0x100, submod), 1) - - sstore(sc, add(and(fslot, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00), and(mload(mc), mask))) - - for { - mc := add(mc, 0x20) - sc := add(sc, 1) - } lt(mc, end) { - sc := add(sc, 1) - mc := add(mc, 0x20) - } { - sstore(sc, mload(mc)) - } - - mask := exp(0x100, sub(mc, end)) - - sstore(sc, mul(div(mload(mc), mask), mask)) - } - default { - // get the keccak hash to get the contents of the array - mstore(0x0, _preBytes.slot) - // Start copying to the last used word of the stored array. - let sc := add(keccak256(0x0, 0x20), div(slength, 32)) - - // save new length - sstore(_preBytes.slot, add(mul(newlength, 2), 1)) - - // Copy over the first `submod` bytes of the new data as in - // case 1 above. - let slengthmod := mod(slength, 32) - // let mlengthmod := mod(mlength, 32) - let submod := sub(32, slengthmod) - let mc := add(_postBytes, submod) - let end := add(_postBytes, mlength) - let mask := sub(exp(0x100, submod), 1) - - sstore(sc, add(sload(sc), and(mload(mc), mask))) - - for { - sc := add(sc, 1) - mc := add(mc, 0x20) - } lt(mc, end) { - sc := add(sc, 1) - mc := add(mc, 0x20) - } { - sstore(sc, mload(mc)) - } - - mask := exp(0x100, sub(mc, end)) - - sstore(sc, mul(div(mload(mc), mask), mask)) - } - } - } - - function slice( - bytes memory _bytes, - uint256 _start, - uint256 _length - ) internal pure returns (bytes memory) { - require(_length + 31 >= _length, "slice_overflow"); - require(_bytes.length >= _start + _length, "slice_outOfBounds"); - - bytes memory tempBytes; - - // solhint-disable-next-line no-inline-assembly - assembly { - switch iszero(_length) - case 0 { - // Get a location of some free memory and store it in tempBytes as - // Solidity does for memory variables. - tempBytes := mload(0x40) - - // The first word of the slice result is potentially a partial - // word read from the original array. To read it, we calculate - // the length of that partial word and start copying that many - // bytes into the array. The first word we copy will start with - // data we don't care about, but the last `lengthmod` bytes will - // land at the beginning of the contents of the new array. When - // we're done copying, we overwrite the full first word with - // the actual length of the slice. - let lengthmod := and(_length, 31) - - // The multiplication in the next line is necessary - // because when slicing multiples of 32 bytes (lengthmod == 0) - // the following copy loop was copying the origin's length - // and then ending prematurely not copying everything it should. - let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod))) - let end := add(mc, _length) - - for { - // The multiplication in the next line has the same exact purpose - // as the one above. - let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start) - } lt(mc, end) { - mc := add(mc, 0x20) - cc := add(cc, 0x20) - } { - mstore(mc, mload(cc)) - } - - mstore(tempBytes, _length) - - //update free-memory pointer - //allocating the array padded to 32 bytes like the compiler does now - mstore(0x40, and(add(mc, 31), not(31))) - } - //if we want a zero-length slice let's just return a zero-length array - default { - tempBytes := mload(0x40) - //zero out the 32 bytes slice we are about to return - //we need to do it because Solidity does not garbage collect - mstore(tempBytes, 0) - - mstore(0x40, add(tempBytes, 0x20)) - } - } - - return tempBytes; - } - - function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) { - require(_bytes.length >= _start + 20, "toAddress_outOfBounds"); - address tempAddress; - - // solhint-disable-next-line no-inline-assembly - assembly { - tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000) - } - - return tempAddress; - } - - function toUint8(bytes memory _bytes, uint256 _start) internal pure returns (uint8) { - require(_bytes.length >= _start + 1, "toUint8_outOfBounds"); - uint8 tempUint; - - // solhint-disable-next-line no-inline-assembly - assembly { - tempUint := mload(add(add(_bytes, 0x1), _start)) - } - - return tempUint; - } - - function toUint16(bytes memory _bytes, uint256 _start) internal pure returns (uint16) { - require(_bytes.length >= _start + 2, "toUint16_outOfBounds"); - uint16 tempUint; - - // solhint-disable-next-line no-inline-assembly - assembly { - tempUint := mload(add(add(_bytes, 0x2), _start)) - } - - return tempUint; - } - - function toUint32(bytes memory _bytes, uint256 _start) internal pure returns (uint32) { - require(_bytes.length >= _start + 4, "toUint32_outOfBounds"); - uint32 tempUint; - - // solhint-disable-next-line no-inline-assembly - assembly { - tempUint := mload(add(add(_bytes, 0x4), _start)) - } - - return tempUint; - } - - function toUint64(bytes memory _bytes, uint256 _start) internal pure returns (uint64) { - require(_bytes.length >= _start + 8, "toUint64_outOfBounds"); - uint64 tempUint; - - // solhint-disable-next-line no-inline-assembly - assembly { - tempUint := mload(add(add(_bytes, 0x8), _start)) - } - - return tempUint; - } - - function toUint96(bytes memory _bytes, uint256 _start) internal pure returns (uint96) { - require(_bytes.length >= _start + 12, "toUint96_outOfBounds"); - uint96 tempUint; - - // solhint-disable-next-line no-inline-assembly - assembly { - tempUint := mload(add(add(_bytes, 0xc), _start)) - } - - return tempUint; - } - - function toUint128(bytes memory _bytes, uint256 _start) internal pure returns (uint128) { - require(_bytes.length >= _start + 16, "toUint128_outOfBounds"); - uint128 tempUint; - - // solhint-disable-next-line no-inline-assembly - assembly { - tempUint := mload(add(add(_bytes, 0x10), _start)) - } - - return tempUint; - } - - function toUint256(bytes memory _bytes, uint256 _start) internal pure returns (uint256) { - require(_bytes.length >= _start + 32, "toUint256_outOfBounds"); - uint256 tempUint; - - // solhint-disable-next-line no-inline-assembly - assembly { - tempUint := mload(add(add(_bytes, 0x20), _start)) - } - - return tempUint; - } - - function toBytes32(bytes memory _bytes, uint256 _start) internal pure returns (bytes32) { - require(_bytes.length >= _start + 32, "toBytes32_outOfBounds"); - bytes32 tempBytes32; - - // solhint-disable-next-line no-inline-assembly - assembly { - tempBytes32 := mload(add(add(_bytes, 0x20), _start)) - } - - return tempBytes32; - } - - function equal(bytes memory _preBytes, bytes memory _postBytes) internal pure returns (bool) { - bool success = true; - - // solhint-disable-next-line no-inline-assembly - assembly { - let length := mload(_preBytes) - - // if lengths don't match the arrays are not equal - switch eq(length, mload(_postBytes)) - case 1 { - // cb is a circuit breaker in the for loop since there's - // no said feature for inline assembly loops - // cb = 1 - don't breaker - // cb = 0 - break - let cb := 1 - - let mc := add(_preBytes, 0x20) - let end := add(mc, length) - - for { - let cc := add(_postBytes, 0x20) - // the next line is the loop condition: - // while(uint256(mc < end) + cb == 2) - } eq(add(lt(mc, end), cb), 2) { - mc := add(mc, 0x20) - cc := add(cc, 0x20) - } { - // if any of these checks fails then arrays are not equal - if iszero(eq(mload(mc), mload(cc))) { - // unsuccess: - success := 0 - cb := 0 - } - } - } - default { - // unsuccess: - success := 0 - } - } - - return success; - } - - function equalStorage(bytes storage _preBytes, bytes memory _postBytes) internal view returns (bool) { - bool success = true; - - // solhint-disable-next-line no-inline-assembly - assembly { - // we know _preBytes_offset is 0 - let fslot := sload(_preBytes.slot) - // Decode the length of the stored array like in concatStorage(). - let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2) - let mlength := mload(_postBytes) - - // if lengths don't match the arrays are not equal - switch eq(slength, mlength) - case 1 { - // slength can contain both the length and contents of the array - // if length < 32 bytes so let's prepare for that - // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage - if iszero(iszero(slength)) { - switch lt(slength, 32) - case 1 { - // blank the last byte which is the length - fslot := mul(div(fslot, 0x100), 0x100) - - if iszero(eq(fslot, mload(add(_postBytes, 0x20)))) { - // unsuccess: - success := 0 - } - } - default { - // cb is a circuit breaker in the for loop since there's - // no said feature for inline assembly loops - // cb = 1 - don't breaker - // cb = 0 - break - let cb := 1 - - // get the keccak hash to get the contents of the array - mstore(0x0, _preBytes.slot) - let sc := keccak256(0x0, 0x20) - - let mc := add(_postBytes, 0x20) - let end := add(mc, mlength) - - // the next line is the loop condition: - // while(uint256(mc < end) + cb == 2) - // solhint-disable-next-line no-empty-blocks - for { - - } eq(add(lt(mc, end), cb), 2) { - sc := add(sc, 1) - mc := add(mc, 0x20) - } { - if iszero(eq(sload(sc), mload(mc))) { - // unsuccess: - success := 0 - cb := 0 - } - } - } - } - } - default { - // unsuccess: - success := 0 - } - } - - return success; - } -} diff --git a/contracts/wormhole721/README.md b/contracts/wormhole721/README.md deleted file mode 100644 index fe69add..0000000 --- a/contracts/wormhole721/README.md +++ /dev/null @@ -1,3 +0,0 @@ -Original code at https://github.com/ndujaLabs/wormhole721 -More info and testing for this code is in the original repo. -The code is here because has not been audited yet. diff --git a/contracts/wormhole721/Wormhole721.sol b/contracts/wormhole721/Wormhole721.sol deleted file mode 100644 index a587d25..0000000 --- a/contracts/wormhole721/Wormhole721.sol +++ /dev/null @@ -1,30 +0,0 @@ -// SPDX-License-Identifier: Apache2 -pragma solidity ^0.8.0; - -import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; -import "../wormhole-tunnel/WormholeTunnel.sol"; - -contract Wormhole721 is ERC721, WormholeTunnel { - // solhint-disable-next-line - constructor(string memory name, string memory symbol) ERC721(name, symbol) {} - - function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721, WormholeTunnel) returns (bool) { - return super.supportsInterface(interfaceId); - } - - function wormholeTransfer( - uint256 tokenID, - uint16 recipientChain, - bytes32 recipient, - uint32 nonce - ) public payable virtual override returns (uint64 sequence) { - _burn(tokenID); - return _wormholeTransferWithValue(tokenID, recipientChain, recipient, nonce, msg.value); - } - - // Complete a transfer from Wormhole - function wormholeCompleteTransfer(bytes memory encodedVm) public virtual override { - (address to, uint256 tokenId) = _wormholeCompleteTransfer(encodedVm); - _safeMint(to, tokenId); - } -} diff --git a/contracts/wormhole721/Wormhole721Upgradeable.sol b/contracts/wormhole721/Wormhole721Upgradeable.sol deleted file mode 100644 index 872af76..0000000 --- a/contracts/wormhole721/Wormhole721Upgradeable.sol +++ /dev/null @@ -1,41 +0,0 @@ -// SPDX-License-Identifier: Apache2 -pragma solidity ^0.8.0; - -import "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol"; -import "../wormhole-tunnel/WormholeTunnelUpgradeable.sol"; - -contract Wormhole721Upgradeable is ERC721Upgradeable, WormholeTunnelUpgradeable { - // solhint-disable-next-line func-name-mixedcase - function __Wormhole721_init(string memory name, string memory symbol) internal virtual initializer { - __WormholeTunnel_init(); - __ERC721_init(name, symbol); - } - - function supportsInterface(bytes4 interfaceId) - public - view - virtual - override(ERC721Upgradeable, WormholeTunnelUpgradeable) - returns (bool) - { - return super.supportsInterface(interfaceId); - } - - function wormholeTransfer( - uint256 tokenID, - uint16 recipientChain, - bytes32 recipient, - uint32 nonce - ) public payable virtual override returns (uint64 sequence) { - _burn(tokenID); - return _wormholeTransferWithValue(tokenID, recipientChain, recipient, nonce, msg.value); - } - - // Complete a transfer from Wormhole - function wormholeCompleteTransfer(bytes memory encodedVm) public virtual override { - (address to, uint256 tokenId) = _wormholeCompleteTransfer(encodedVm); - _safeMint(to, tokenId); - } - - uint256[50] private __gap; -} diff --git a/package.json b/package.json index 05cbfe6..046addf 100644 --- a/package.json +++ b/package.json @@ -6,8 +6,8 @@ "scripts": { "test": "NODE_ENV=test npx hardhat test", "test:gas": "NODE_ENV=test GAS_REPORT=yes npx hardhat test", - "compile": "npx hardhat compile", - "size": "npx hardhat size-contracts", + "compile": "NODE_ENV=test npx hardhat compile", + "size": "NODE_ENV=test npx hardhat size-contracts", "lint": "prettier --write 'contracts/**/*.sol' && solhint 'contracts/**/*.sol'", "format": "npx prettier --write ./**/*.js", "coverage": "npx hardhat coverage", @@ -18,19 +18,20 @@ "license": "MIT", "devDependencies": { "@ethersproject/contracts": "^5.6.2", + "@ndujalabs/wormhole-tunnel": "^0.4.1", + "@ndujalabs/wormhole721": "^0.5.4", "@nomiclabs/hardhat-ethers": "^2.0.3", "@nomiclabs/hardhat-etherscan": "^2.1.8", "@nomiclabs/hardhat-waffle": "^2.0.1", "@openzeppelin/contracts": "4.5.0", "@openzeppelin/contracts-upgradeable": "4.5.0", - "@openzeppelin/hardhat-upgrades": "^1.21.0", + "@openzeppelin/hardhat-upgrades": "^1.22.1", "@poanet/solidity-flattener": "^3.0.6", "chai": "^4.3.4", "cryptoenv": "^0.2.0", "csv-parse": "^5.3.3", "dotenv": "^11.0.0", "ethereum-waffle": "^3.4.0", - "ethers": "^5.5.2", "fs-extra": "^10.0.0", "glob": "*", "hardhat": "^2.7.1", @@ -52,5 +53,8 @@ }, "lint-staged": { "*.js": "prettier --write" + }, + "dependencies": { + "ethers": "5" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a5b5018..a409bc8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -2,19 +2,21 @@ lockfileVersion: 5.4 specifiers: '@ethersproject/contracts': ^5.6.2 + '@ndujalabs/wormhole-tunnel': ^0.4.1 + '@ndujalabs/wormhole721': ^0.5.4 '@nomiclabs/hardhat-ethers': ^2.0.3 '@nomiclabs/hardhat-etherscan': ^2.1.8 '@nomiclabs/hardhat-waffle': ^2.0.1 '@openzeppelin/contracts': 4.5.0 '@openzeppelin/contracts-upgradeable': 4.5.0 - '@openzeppelin/hardhat-upgrades': ^1.21.0 + '@openzeppelin/hardhat-upgrades': ^1.22.1 '@poanet/solidity-flattener': ^3.0.6 chai: ^4.3.4 cryptoenv: ^0.2.0 csv-parse: ^5.3.3 dotenv: ^11.0.0 ethereum-waffle: ^3.4.0 - ethers: ^5.5.2 + ethers: '5' fs-extra: ^10.0.0 glob: '*' hardhat: ^2.7.1 @@ -34,21 +36,25 @@ specifiers: solidity-coverage: ^0.7.21 typescript: ^4.7.3 +dependencies: + ethers: 5.5.4 + devDependencies: '@ethersproject/contracts': 5.6.2 + '@ndujalabs/wormhole-tunnel': 0.4.1 + '@ndujalabs/wormhole721': 0.5.4 '@nomiclabs/hardhat-ethers': 2.0.4_ethers@5.5.4+hardhat@2.8.3 '@nomiclabs/hardhat-etherscan': 2.1.8_hardhat@2.8.3 '@nomiclabs/hardhat-waffle': 2.0.2_6oy2mnnnyf6xpql55mxsdlbst4 '@openzeppelin/contracts': 4.5.0 '@openzeppelin/contracts-upgradeable': 4.5.0 - '@openzeppelin/hardhat-upgrades': 1.21.0_kt2bb34tk6drucgqtuhpnmxvru + '@openzeppelin/hardhat-upgrades': 1.22.1_kt2bb34tk6drucgqtuhpnmxvru '@poanet/solidity-flattener': 3.0.6_glob@7.2.0 chai: 4.3.6 cryptoenv: 0.2.0 csv-parse: 5.3.3 dotenv: 11.0.0 ethereum-waffle: 3.4.0_typescript@4.7.3 - ethers: 5.5.4 fs-extra: 10.0.0 glob: 7.2.0 hardhat: 2.8.3 @@ -158,7 +164,7 @@ packages: resolution: {integrity: sha512-h9yChF7IkpJLODg/o9/jlwKwTcXJLSEIq3gewgwUJuBHnhPkJGekcZvsTbximYc+e42QUZrDUATSuTCIryeCEA==} engines: {node: '>=10.0'} dependencies: - '@ethersproject/abi': 5.5.0 + '@ethersproject/abi': 5.6.4 ethers: 5.5.4 transitivePeerDependencies: - bufferutil @@ -279,16 +285,15 @@ packages: /@ethersproject/abi/5.5.0: resolution: {integrity: sha512-loW7I4AohP5KycATvc0MgujU6JyCHPqHdeoo9z3Nr9xEiNioxa65ccdm1+fsoJhkuhdRtfcL8cfyGamz2AxZ5w==} dependencies: - '@ethersproject/address': 5.5.0 - '@ethersproject/bignumber': 5.5.0 - '@ethersproject/bytes': 5.5.0 - '@ethersproject/constants': 5.5.0 - '@ethersproject/hash': 5.5.0 - '@ethersproject/keccak256': 5.5.0 - '@ethersproject/logger': 5.5.0 - '@ethersproject/properties': 5.5.0 - '@ethersproject/strings': 5.5.0 - dev: true + '@ethersproject/address': 5.6.1 + '@ethersproject/bignumber': 5.6.2 + '@ethersproject/bytes': 5.6.1 + '@ethersproject/constants': 5.6.1 + '@ethersproject/hash': 5.6.1 + '@ethersproject/keccak256': 5.6.1 + '@ethersproject/logger': 5.6.0 + '@ethersproject/properties': 5.6.0 + '@ethersproject/strings': 5.6.1 /@ethersproject/abi/5.6.4: resolution: {integrity: sha512-TTeZUlCeIHG6527/2goZA6gW5F8Emoc7MrZDC7hhP84aRGvW3TEdTnZR08Ls88YXM1m2SuK42Osw/jSi3uO8gg==} @@ -302,19 +307,17 @@ packages: '@ethersproject/logger': 5.6.0 '@ethersproject/properties': 5.6.0 '@ethersproject/strings': 5.6.1 - dev: true /@ethersproject/abstract-provider/5.5.1: resolution: {integrity: sha512-m+MA/ful6eKbxpr99xUYeRvLkfnlqzrF8SZ46d/xFB1A7ZVknYc/sXJG0RcufF52Qn2jeFj1hhcoQ7IXjNKUqg==} dependencies: - '@ethersproject/bignumber': 5.5.0 - '@ethersproject/bytes': 5.5.0 - '@ethersproject/logger': 5.5.0 - '@ethersproject/networks': 5.5.2 - '@ethersproject/properties': 5.5.0 - '@ethersproject/transactions': 5.5.0 - '@ethersproject/web': 5.5.1 - dev: true + '@ethersproject/bignumber': 5.6.2 + '@ethersproject/bytes': 5.6.1 + '@ethersproject/logger': 5.6.0 + '@ethersproject/networks': 5.6.4 + '@ethersproject/properties': 5.6.0 + '@ethersproject/transactions': 5.6.2 + '@ethersproject/web': 5.6.1 /@ethersproject/abstract-provider/5.6.1: resolution: {integrity: sha512-BxlIgogYJtp1FS8Muvj8YfdClk3unZH0vRMVX791Z9INBNT/kuACZ9GzaY1Y4yFq+YSy6/w4gzj3HCRKrK9hsQ==} @@ -326,17 +329,15 @@ packages: '@ethersproject/properties': 5.6.0 '@ethersproject/transactions': 5.6.2 '@ethersproject/web': 5.6.1 - dev: true /@ethersproject/abstract-signer/5.5.0: resolution: {integrity: sha512-lj//7r250MXVLKI7sVarXAbZXbv9P50lgmJQGr2/is82EwEb8r7HrxsmMqAjTsztMYy7ohrIhGMIml+Gx4D3mA==} dependencies: - '@ethersproject/abstract-provider': 5.5.1 - '@ethersproject/bignumber': 5.5.0 - '@ethersproject/bytes': 5.5.0 - '@ethersproject/logger': 5.5.0 - '@ethersproject/properties': 5.5.0 - dev: true + '@ethersproject/abstract-provider': 5.6.1 + '@ethersproject/bignumber': 5.6.2 + '@ethersproject/bytes': 5.6.1 + '@ethersproject/logger': 5.6.0 + '@ethersproject/properties': 5.6.0 /@ethersproject/abstract-signer/5.6.2: resolution: {integrity: sha512-n1r6lttFBG0t2vNiI3HoWaS/KdOt8xyDjzlP2cuevlWLG6EX0OwcKLyG/Kp/cuwNxdy/ous+R/DEMdTUwWQIjQ==} @@ -346,17 +347,15 @@ packages: '@ethersproject/bytes': 5.6.1 '@ethersproject/logger': 5.6.0 '@ethersproject/properties': 5.6.0 - dev: true /@ethersproject/address/5.5.0: resolution: {integrity: sha512-l4Nj0eWlTUh6ro5IbPTgbpT4wRbdH5l8CQf7icF7sb/SI3Nhd9Y9HzhonTSTi6CefI0necIw7LJqQPopPLZyWw==} dependencies: - '@ethersproject/bignumber': 5.5.0 - '@ethersproject/bytes': 5.5.0 - '@ethersproject/keccak256': 5.5.0 - '@ethersproject/logger': 5.5.0 - '@ethersproject/rlp': 5.5.0 - dev: true + '@ethersproject/bignumber': 5.6.2 + '@ethersproject/bytes': 5.6.1 + '@ethersproject/keccak256': 5.6.1 + '@ethersproject/logger': 5.6.0 + '@ethersproject/rlp': 5.6.1 /@ethersproject/address/5.6.1: resolution: {integrity: sha512-uOgF0kS5MJv9ZvCz7x6T2EXJSzotiybApn4XlOgoTX0xdtyVIJ7pF+6cGPxiEq/dpBiTfMiw7Yc81JcwhSYA0Q==} @@ -366,34 +365,29 @@ packages: '@ethersproject/keccak256': 5.6.1 '@ethersproject/logger': 5.6.0 '@ethersproject/rlp': 5.6.1 - dev: true /@ethersproject/base64/5.5.0: resolution: {integrity: sha512-tdayUKhU1ljrlHzEWbStXazDpsx4eg1dBXUSI6+mHlYklOXoXF6lZvw8tnD6oVaWfnMxAgRSKROg3cVKtCcppA==} dependencies: - '@ethersproject/bytes': 5.5.0 - dev: true + '@ethersproject/bytes': 5.6.1 /@ethersproject/base64/5.6.1: resolution: {integrity: sha512-qB76rjop6a0RIYYMiB4Eh/8n+Hxu2NIZm8S/Q7kNo5pmZfXhHGHmS4MinUainiBC54SCyRnwzL+KZjj8zbsSsw==} dependencies: '@ethersproject/bytes': 5.6.1 - dev: true /@ethersproject/basex/5.5.0: resolution: {integrity: sha512-ZIodwhHpVJ0Y3hUCfUucmxKsWQA5TMnavp5j/UOuDdzZWzJlRmuOjcTMIGgHCYuZmHt36BfiSyQPSRskPxbfaQ==} dependencies: - '@ethersproject/bytes': 5.5.0 - '@ethersproject/properties': 5.5.0 - dev: true + '@ethersproject/bytes': 5.6.1 + '@ethersproject/properties': 5.6.0 /@ethersproject/bignumber/5.5.0: resolution: {integrity: sha512-6Xytlwvy6Rn3U3gKEc1vP7nR92frHkv6wtVr95LFR3jREXiCPzdWxKQ1cx4JGQBXxcguAwjA8murlYN2TSiEbg==} dependencies: - '@ethersproject/bytes': 5.5.0 - '@ethersproject/logger': 5.5.0 + '@ethersproject/bytes': 5.6.1 + '@ethersproject/logger': 5.6.0 bn.js: 4.12.0 - dev: true /@ethersproject/bignumber/5.6.2: resolution: {integrity: sha512-v7+EEUbhGqT3XJ9LMPsKvXYHFc8eHxTowFCG/HgJErmq4XHJ2WR7aeyICg3uTOAQ7Icn0GFHAohXEhxQHq4Ubw==} @@ -401,46 +395,40 @@ packages: '@ethersproject/bytes': 5.6.1 '@ethersproject/logger': 5.6.0 bn.js: 5.2.1 - dev: true /@ethersproject/bytes/5.5.0: resolution: {integrity: sha512-ABvc7BHWhZU9PNM/tANm/Qx4ostPGadAuQzWTr3doklZOhDlmcBqclrQe/ZXUIj3K8wC28oYeuRa+A37tX9kog==} dependencies: - '@ethersproject/logger': 5.5.0 - dev: true + '@ethersproject/logger': 5.6.0 /@ethersproject/bytes/5.6.1: resolution: {integrity: sha512-NwQt7cKn5+ZE4uDn+X5RAXLp46E1chXoaMmrxAyA0rblpxz8t58lVkrHXoRIn0lz1joQElQ8410GqhTqMOwc6g==} dependencies: '@ethersproject/logger': 5.6.0 - dev: true /@ethersproject/constants/5.5.0: resolution: {integrity: sha512-2MsRRVChkvMWR+GyMGY4N1sAX9Mt3J9KykCsgUFd/1mwS0UH1qw+Bv9k1UJb3X3YJYFco9H20pjSlOIfCG5HYQ==} dependencies: - '@ethersproject/bignumber': 5.5.0 - dev: true + '@ethersproject/bignumber': 5.6.2 /@ethersproject/constants/5.6.1: resolution: {integrity: sha512-QSq9WVnZbxXYFftrjSjZDUshp6/eKp6qrtdBtUCm0QxCV5z1fG/w3kdlcsjMCQuQHUnAclKoK7XpXMezhRDOLg==} dependencies: '@ethersproject/bignumber': 5.6.2 - dev: true /@ethersproject/contracts/5.5.0: resolution: {integrity: sha512-2viY7NzyvJkh+Ug17v7g3/IJC8HqZBDcOjYARZLdzRxrfGlRgmYgl6xPRKVbEzy1dWKw/iv7chDcS83pg6cLxg==} dependencies: - '@ethersproject/abi': 5.5.0 - '@ethersproject/abstract-provider': 5.5.1 - '@ethersproject/abstract-signer': 5.5.0 - '@ethersproject/address': 5.5.0 - '@ethersproject/bignumber': 5.5.0 - '@ethersproject/bytes': 5.5.0 - '@ethersproject/constants': 5.5.0 - '@ethersproject/logger': 5.5.0 - '@ethersproject/properties': 5.5.0 - '@ethersproject/transactions': 5.5.0 - dev: true + '@ethersproject/abi': 5.6.4 + '@ethersproject/abstract-provider': 5.6.1 + '@ethersproject/abstract-signer': 5.6.2 + '@ethersproject/address': 5.6.1 + '@ethersproject/bignumber': 5.6.2 + '@ethersproject/bytes': 5.6.1 + '@ethersproject/constants': 5.6.1 + '@ethersproject/logger': 5.6.0 + '@ethersproject/properties': 5.6.0 + '@ethersproject/transactions': 5.6.2 /@ethersproject/contracts/5.6.2: resolution: {integrity: sha512-hguUA57BIKi6WY0kHvZp6PwPlWF87MCeB4B7Z7AbUpTxfFXFdn/3b0GmjZPagIHS+3yhcBJDnuEfU4Xz+Ks/8g==} @@ -460,15 +448,14 @@ packages: /@ethersproject/hash/5.5.0: resolution: {integrity: sha512-dnGVpK1WtBjmnp3mUT0PlU2MpapnwWI0PibldQEq1408tQBAbZpPidkWoVVuNMOl/lISO3+4hXZWCL3YV7qzfg==} dependencies: - '@ethersproject/abstract-signer': 5.5.0 - '@ethersproject/address': 5.5.0 - '@ethersproject/bignumber': 5.5.0 - '@ethersproject/bytes': 5.5.0 - '@ethersproject/keccak256': 5.5.0 - '@ethersproject/logger': 5.5.0 - '@ethersproject/properties': 5.5.0 - '@ethersproject/strings': 5.5.0 - dev: true + '@ethersproject/abstract-signer': 5.6.2 + '@ethersproject/address': 5.6.1 + '@ethersproject/bignumber': 5.6.2 + '@ethersproject/bytes': 5.6.1 + '@ethersproject/keccak256': 5.6.1 + '@ethersproject/logger': 5.6.0 + '@ethersproject/properties': 5.6.0 + '@ethersproject/strings': 5.6.1 /@ethersproject/hash/5.6.1: resolution: {integrity: sha512-L1xAHurbaxG8VVul4ankNX5HgQ8PNCTrnVXEiFnE9xoRnaUcgfD12tZINtDinSllxPLCtGwguQxJ5E6keE84pA==} @@ -481,162 +468,144 @@ packages: '@ethersproject/logger': 5.6.0 '@ethersproject/properties': 5.6.0 '@ethersproject/strings': 5.6.1 - dev: true /@ethersproject/hdnode/5.5.0: resolution: {integrity: sha512-mcSOo9zeUg1L0CoJH7zmxwUG5ggQHU1UrRf8jyTYy6HxdZV+r0PBoL1bxr+JHIPXRzS6u/UW4mEn43y0tmyF8Q==} dependencies: - '@ethersproject/abstract-signer': 5.5.0 + '@ethersproject/abstract-signer': 5.6.2 '@ethersproject/basex': 5.5.0 - '@ethersproject/bignumber': 5.5.0 - '@ethersproject/bytes': 5.5.0 - '@ethersproject/logger': 5.5.0 + '@ethersproject/bignumber': 5.6.2 + '@ethersproject/bytes': 5.6.1 + '@ethersproject/logger': 5.6.0 '@ethersproject/pbkdf2': 5.5.0 - '@ethersproject/properties': 5.5.0 + '@ethersproject/properties': 5.6.0 '@ethersproject/sha2': 5.5.0 - '@ethersproject/signing-key': 5.5.0 - '@ethersproject/strings': 5.5.0 - '@ethersproject/transactions': 5.5.0 + '@ethersproject/signing-key': 5.6.2 + '@ethersproject/strings': 5.6.1 + '@ethersproject/transactions': 5.6.2 '@ethersproject/wordlists': 5.5.0 - dev: true /@ethersproject/json-wallets/5.5.0: resolution: {integrity: sha512-9lA21XQnCdcS72xlBn1jfQdj2A1VUxZzOzi9UkNdnokNKke/9Ya2xA9aIK1SC3PQyBDLt4C+dfps7ULpkvKikQ==} dependencies: - '@ethersproject/abstract-signer': 5.5.0 - '@ethersproject/address': 5.5.0 - '@ethersproject/bytes': 5.5.0 + '@ethersproject/abstract-signer': 5.6.2 + '@ethersproject/address': 5.6.1 + '@ethersproject/bytes': 5.6.1 '@ethersproject/hdnode': 5.5.0 - '@ethersproject/keccak256': 5.5.0 - '@ethersproject/logger': 5.5.0 + '@ethersproject/keccak256': 5.6.1 + '@ethersproject/logger': 5.6.0 '@ethersproject/pbkdf2': 5.5.0 - '@ethersproject/properties': 5.5.0 + '@ethersproject/properties': 5.6.0 '@ethersproject/random': 5.5.1 - '@ethersproject/strings': 5.5.0 - '@ethersproject/transactions': 5.5.0 + '@ethersproject/strings': 5.6.1 + '@ethersproject/transactions': 5.6.2 aes-js: 3.0.0 scrypt-js: 3.0.1 - dev: true /@ethersproject/keccak256/5.5.0: resolution: {integrity: sha512-5VoFCTjo2rYbBe1l2f4mccaRFN/4VQEYFwwn04aJV2h7qf4ZvI2wFxUE1XOX+snbwCLRzIeikOqtAoPwMza9kg==} dependencies: - '@ethersproject/bytes': 5.5.0 + '@ethersproject/bytes': 5.6.1 js-sha3: 0.8.0 - dev: true /@ethersproject/keccak256/5.6.1: resolution: {integrity: sha512-bB7DQHCTRDooZZdL3lk9wpL0+XuG3XLGHLh3cePnybsO3V0rdCAOQGpn/0R3aODmnTOOkCATJiD2hnL+5bwthA==} dependencies: '@ethersproject/bytes': 5.6.1 js-sha3: 0.8.0 - dev: true /@ethersproject/logger/5.5.0: resolution: {integrity: sha512-rIY/6WPm7T8n3qS2vuHTUBPdXHl+rGxWxW5okDfo9J4Z0+gRRZT0msvUdIJkE4/HS29GUMziwGaaKO2bWONBrg==} - dev: true /@ethersproject/logger/5.6.0: resolution: {integrity: sha512-BiBWllUROH9w+P21RzoxJKzqoqpkyM1pRnEKG69bulE9TSQD8SAIvTQqIMZmmCO8pUNkgLP1wndX1gKghSpBmg==} - dev: true /@ethersproject/networks/5.5.2: resolution: {integrity: sha512-NEqPxbGBfy6O3x4ZTISb90SjEDkWYDUbEeIFhJly0F7sZjoQMnj5KYzMSkMkLKZ+1fGpx00EDpHQCy6PrDupkQ==} dependencies: - '@ethersproject/logger': 5.5.0 - dev: true + '@ethersproject/logger': 5.6.0 /@ethersproject/networks/5.6.4: resolution: {integrity: sha512-KShHeHPahHI2UlWdtDMn2lJETcbtaJge4k7XSjDR9h79QTd6yQJmv6Cp2ZA4JdqWnhszAOLSuJEd9C0PRw7hSQ==} dependencies: '@ethersproject/logger': 5.6.0 - dev: true /@ethersproject/pbkdf2/5.5.0: resolution: {integrity: sha512-SaDvQFvXPnz1QGpzr6/HToLifftSXGoXrbpZ6BvoZhmx4bNLHrxDe8MZisuecyOziP1aVEwzC2Hasj+86TgWVg==} dependencies: - '@ethersproject/bytes': 5.5.0 + '@ethersproject/bytes': 5.6.1 '@ethersproject/sha2': 5.5.0 - dev: true /@ethersproject/properties/5.5.0: resolution: {integrity: sha512-l3zRQg3JkD8EL3CPjNK5g7kMx4qSwiR60/uk5IVjd3oq1MZR5qUg40CNOoEJoX5wc3DyY5bt9EbMk86C7x0DNA==} dependencies: - '@ethersproject/logger': 5.5.0 - dev: true + '@ethersproject/logger': 5.6.0 /@ethersproject/properties/5.6.0: resolution: {integrity: sha512-szoOkHskajKePTJSZ46uHUWWkbv7TzP2ypdEK6jGMqJaEt2sb0jCgfBo0gH0m2HBpRixMuJ6TBRaQCF7a9DoCg==} dependencies: '@ethersproject/logger': 5.6.0 - dev: true /@ethersproject/providers/5.5.3: resolution: {integrity: sha512-ZHXxXXXWHuwCQKrgdpIkbzMNJMvs+9YWemanwp1fA7XZEv7QlilseysPvQe0D7Q7DlkJX/w/bGA1MdgK2TbGvA==} dependencies: - '@ethersproject/abstract-provider': 5.5.1 - '@ethersproject/abstract-signer': 5.5.0 - '@ethersproject/address': 5.5.0 + '@ethersproject/abstract-provider': 5.6.1 + '@ethersproject/abstract-signer': 5.6.2 + '@ethersproject/address': 5.6.1 '@ethersproject/basex': 5.5.0 - '@ethersproject/bignumber': 5.5.0 - '@ethersproject/bytes': 5.5.0 - '@ethersproject/constants': 5.5.0 - '@ethersproject/hash': 5.5.0 - '@ethersproject/logger': 5.5.0 - '@ethersproject/networks': 5.5.2 - '@ethersproject/properties': 5.5.0 + '@ethersproject/bignumber': 5.6.2 + '@ethersproject/bytes': 5.6.1 + '@ethersproject/constants': 5.6.1 + '@ethersproject/hash': 5.6.1 + '@ethersproject/logger': 5.6.0 + '@ethersproject/networks': 5.6.4 + '@ethersproject/properties': 5.6.0 '@ethersproject/random': 5.5.1 - '@ethersproject/rlp': 5.5.0 + '@ethersproject/rlp': 5.6.1 '@ethersproject/sha2': 5.5.0 - '@ethersproject/strings': 5.5.0 - '@ethersproject/transactions': 5.5.0 - '@ethersproject/web': 5.5.1 + '@ethersproject/strings': 5.6.1 + '@ethersproject/transactions': 5.6.2 + '@ethersproject/web': 5.6.1 bech32: 1.1.4 ws: 7.4.6 transitivePeerDependencies: - bufferutil - utf-8-validate - dev: true /@ethersproject/random/5.5.1: resolution: {integrity: sha512-YaU2dQ7DuhL5Au7KbcQLHxcRHfgyNgvFV4sQOo0HrtW3Zkrc9ctWNz8wXQ4uCSfSDsqX2vcjhroxU5RQRV0nqA==} dependencies: - '@ethersproject/bytes': 5.5.0 - '@ethersproject/logger': 5.5.0 - dev: true + '@ethersproject/bytes': 5.6.1 + '@ethersproject/logger': 5.6.0 /@ethersproject/rlp/5.5.0: resolution: {integrity: sha512-hLv8XaQ8PTI9g2RHoQGf/WSxBfTB/NudRacbzdxmst5VHAqd1sMibWG7SENzT5Dj3yZ3kJYx+WiRYEcQTAkcYA==} dependencies: - '@ethersproject/bytes': 5.5.0 - '@ethersproject/logger': 5.5.0 - dev: true + '@ethersproject/bytes': 5.6.1 + '@ethersproject/logger': 5.6.0 /@ethersproject/rlp/5.6.1: resolution: {integrity: sha512-uYjmcZx+DKlFUk7a5/W9aQVaoEC7+1MOBgNtvNg13+RnuUwT4F0zTovC0tmay5SmRslb29V1B7Y5KCri46WhuQ==} dependencies: '@ethersproject/bytes': 5.6.1 '@ethersproject/logger': 5.6.0 - dev: true /@ethersproject/sha2/5.5.0: resolution: {integrity: sha512-B5UBoglbCiHamRVPLA110J+2uqsifpZaTmid2/7W5rbtYVz6gus6/hSDieIU/6gaKIDcOj12WnOdiymEUHIAOA==} dependencies: - '@ethersproject/bytes': 5.5.0 - '@ethersproject/logger': 5.5.0 + '@ethersproject/bytes': 5.6.1 + '@ethersproject/logger': 5.6.0 hash.js: 1.1.7 - dev: true /@ethersproject/signing-key/5.5.0: resolution: {integrity: sha512-5VmseH7qjtNmDdZBswavhotYbWB0bOwKIlOTSlX14rKn5c11QmJwGt4GHeo7NrL/Ycl7uo9AHvEqs5xZgFBTng==} dependencies: - '@ethersproject/bytes': 5.5.0 - '@ethersproject/logger': 5.5.0 - '@ethersproject/properties': 5.5.0 + '@ethersproject/bytes': 5.6.1 + '@ethersproject/logger': 5.6.0 + '@ethersproject/properties': 5.6.0 bn.js: 4.12.0 elliptic: 6.5.4 hash.js: 1.1.7 - dev: true /@ethersproject/signing-key/5.6.2: resolution: {integrity: sha512-jVbu0RuP7EFpw82vHcL+GP35+KaNruVAZM90GxgQnGqB6crhBqW/ozBfFvdeImtmb4qPko0uxXjn8l9jpn0cwQ==} @@ -647,26 +616,23 @@ packages: bn.js: 5.2.1 elliptic: 6.5.4 hash.js: 1.1.7 - dev: true /@ethersproject/solidity/5.5.0: resolution: {integrity: sha512-9NgZs9LhGMj6aCtHXhtmFQ4AN4sth5HuFXVvAQtzmm0jpSCNOTGtrHZJAeYTh7MBjRR8brylWZxBZR9zDStXbw==} dependencies: - '@ethersproject/bignumber': 5.5.0 - '@ethersproject/bytes': 5.5.0 - '@ethersproject/keccak256': 5.5.0 - '@ethersproject/logger': 5.5.0 + '@ethersproject/bignumber': 5.6.2 + '@ethersproject/bytes': 5.6.1 + '@ethersproject/keccak256': 5.6.1 + '@ethersproject/logger': 5.6.0 '@ethersproject/sha2': 5.5.0 - '@ethersproject/strings': 5.5.0 - dev: true + '@ethersproject/strings': 5.6.1 /@ethersproject/strings/5.5.0: resolution: {integrity: sha512-9fy3TtF5LrX/wTrBaT8FGE6TDJyVjOvXynXJz5MT5azq+E6D92zuKNx7i29sWW2FjVOaWjAsiZ1ZWznuduTIIQ==} dependencies: - '@ethersproject/bytes': 5.5.0 - '@ethersproject/constants': 5.5.0 - '@ethersproject/logger': 5.5.0 - dev: true + '@ethersproject/bytes': 5.6.1 + '@ethersproject/constants': 5.6.1 + '@ethersproject/logger': 5.6.0 /@ethersproject/strings/5.6.1: resolution: {integrity: sha512-2X1Lgk6Jyfg26MUnsHiT456U9ijxKUybz8IM1Vih+NJxYtXhmvKBcHOmvGqpFSVJ0nQ4ZCoIViR8XlRw1v/+Cw==} @@ -674,21 +640,19 @@ packages: '@ethersproject/bytes': 5.6.1 '@ethersproject/constants': 5.6.1 '@ethersproject/logger': 5.6.0 - dev: true /@ethersproject/transactions/5.5.0: resolution: {integrity: sha512-9RZYSKX26KfzEd/1eqvv8pLauCKzDTub0Ko4LfIgaERvRuwyaNV78mJs7cpIgZaDl6RJui4o49lHwwCM0526zA==} dependencies: - '@ethersproject/address': 5.5.0 - '@ethersproject/bignumber': 5.5.0 - '@ethersproject/bytes': 5.5.0 - '@ethersproject/constants': 5.5.0 - '@ethersproject/keccak256': 5.5.0 - '@ethersproject/logger': 5.5.0 - '@ethersproject/properties': 5.5.0 - '@ethersproject/rlp': 5.5.0 - '@ethersproject/signing-key': 5.5.0 - dev: true + '@ethersproject/address': 5.6.1 + '@ethersproject/bignumber': 5.6.2 + '@ethersproject/bytes': 5.6.1 + '@ethersproject/constants': 5.6.1 + '@ethersproject/keccak256': 5.6.1 + '@ethersproject/logger': 5.6.0 + '@ethersproject/properties': 5.6.0 + '@ethersproject/rlp': 5.6.1 + '@ethersproject/signing-key': 5.6.2 /@ethersproject/transactions/5.6.2: resolution: {integrity: sha512-BuV63IRPHmJvthNkkt9G70Ullx6AcM+SDc+a8Aw/8Yew6YwT51TcBKEp1P4oOQ/bP25I18JJr7rcFRgFtU9B2Q==} @@ -702,45 +666,41 @@ packages: '@ethersproject/properties': 5.6.0 '@ethersproject/rlp': 5.6.1 '@ethersproject/signing-key': 5.6.2 - dev: true /@ethersproject/units/5.5.0: resolution: {integrity: sha512-7+DpjiZk4v6wrikj+TCyWWa9dXLNU73tSTa7n0TSJDxkYbV3Yf1eRh9ToMLlZtuctNYu9RDNNy2USq3AdqSbag==} dependencies: - '@ethersproject/bignumber': 5.5.0 - '@ethersproject/constants': 5.5.0 - '@ethersproject/logger': 5.5.0 - dev: true + '@ethersproject/bignumber': 5.6.2 + '@ethersproject/constants': 5.6.1 + '@ethersproject/logger': 5.6.0 /@ethersproject/wallet/5.5.0: resolution: {integrity: sha512-Mlu13hIctSYaZmUOo7r2PhNSd8eaMPVXe1wxrz4w4FCE4tDYBywDH+bAR1Xz2ADyXGwqYMwstzTrtUVIsKDO0Q==} dependencies: - '@ethersproject/abstract-provider': 5.5.1 - '@ethersproject/abstract-signer': 5.5.0 - '@ethersproject/address': 5.5.0 - '@ethersproject/bignumber': 5.5.0 - '@ethersproject/bytes': 5.5.0 - '@ethersproject/hash': 5.5.0 + '@ethersproject/abstract-provider': 5.6.1 + '@ethersproject/abstract-signer': 5.6.2 + '@ethersproject/address': 5.6.1 + '@ethersproject/bignumber': 5.6.2 + '@ethersproject/bytes': 5.6.1 + '@ethersproject/hash': 5.6.1 '@ethersproject/hdnode': 5.5.0 '@ethersproject/json-wallets': 5.5.0 - '@ethersproject/keccak256': 5.5.0 - '@ethersproject/logger': 5.5.0 - '@ethersproject/properties': 5.5.0 + '@ethersproject/keccak256': 5.6.1 + '@ethersproject/logger': 5.6.0 + '@ethersproject/properties': 5.6.0 '@ethersproject/random': 5.5.1 - '@ethersproject/signing-key': 5.5.0 - '@ethersproject/transactions': 5.5.0 + '@ethersproject/signing-key': 5.6.2 + '@ethersproject/transactions': 5.6.2 '@ethersproject/wordlists': 5.5.0 - dev: true /@ethersproject/web/5.5.1: resolution: {integrity: sha512-olvLvc1CB12sREc1ROPSHTdFCdvMh0J5GSJYiQg2D0hdD4QmJDy8QYDb1CvoqD/bF1c++aeKv2sR5uduuG9dQg==} dependencies: - '@ethersproject/base64': 5.5.0 - '@ethersproject/bytes': 5.5.0 - '@ethersproject/logger': 5.5.0 - '@ethersproject/properties': 5.5.0 - '@ethersproject/strings': 5.5.0 - dev: true + '@ethersproject/base64': 5.6.1 + '@ethersproject/bytes': 5.6.1 + '@ethersproject/logger': 5.6.0 + '@ethersproject/properties': 5.6.0 + '@ethersproject/strings': 5.6.1 /@ethersproject/web/5.6.1: resolution: {integrity: sha512-/vSyzaQlNXkO1WV+RneYKqCJwualcUdx/Z3gseVovZP0wIlOFcCE1hkRhKBH8ImKbGQbMl9EAAyJFrJu7V0aqA==} @@ -750,22 +710,35 @@ packages: '@ethersproject/logger': 5.6.0 '@ethersproject/properties': 5.6.0 '@ethersproject/strings': 5.6.1 - dev: true /@ethersproject/wordlists/5.5.0: resolution: {integrity: sha512-bL0UTReWDiaQJJYOC9sh/XcRu/9i2jMrzf8VLRmPKx58ckSlOJiohODkECCO50dtLZHcGU6MLXQ4OOrgBwP77Q==} dependencies: - '@ethersproject/bytes': 5.5.0 - '@ethersproject/hash': 5.5.0 - '@ethersproject/logger': 5.5.0 - '@ethersproject/properties': 5.5.0 - '@ethersproject/strings': 5.5.0 - dev: true + '@ethersproject/bytes': 5.6.1 + '@ethersproject/hash': 5.6.1 + '@ethersproject/logger': 5.6.0 + '@ethersproject/properties': 5.6.0 + '@ethersproject/strings': 5.6.1 /@multiformats/base-x/4.0.1: resolution: {integrity: sha512-eMk0b9ReBbV23xXU693TAIrLyeO5iTgBZGSJfpqriG8UkYvr/hC9u9pyMlAakDNHWmbhMZCDs6KQO0jzKD8OTw==} dev: true + /@ndujalabs/wormhole-tunnel/0.4.1: + resolution: {integrity: sha512-j4G+9ksT6zvr4LiLPt4H7aZtwrb1SUwJrrA9UpInWL5giGZr/7c6OKPl96Smkbypfiy/jPKqOBUPnryDiKf7OQ==} + dependencies: + '@openzeppelin/contracts': 4.5.0 + '@openzeppelin/contracts-upgradeable': 4.5.0 + dev: true + + /@ndujalabs/wormhole721/0.5.4: + resolution: {integrity: sha512-xLG8cMi2JiiQELwJYgRB0ER8qQoIL2dLpSzOK+dQnarxzpcbwugurLy3L6mad/sjE9nYOKhoIJaedR6w7S+l7Q==} + dependencies: + '@ndujalabs/wormhole-tunnel': 0.4.1 + '@openzeppelin/contracts': 4.5.0 + '@openzeppelin/contracts-upgradeable': 4.5.0 + dev: true + /@nodelib/fs.scandir/2.1.5: resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -839,8 +812,8 @@ packages: resolution: {integrity: sha512-fdkzKPYMjrRiPK6K4y64e6GzULR7R7RwxSigHS8DDp7aWDeoReqsQI+cxHV1UuhAqX69L1lAaWDxenfP+xiqzA==} dev: true - /@openzeppelin/hardhat-upgrades/1.21.0_kt2bb34tk6drucgqtuhpnmxvru: - resolution: {integrity: sha512-Kwl7IN0Hlhj4HluMTTl0DrtU90OI/Q6rG3sAyd2pv3fababe9EuZqs9DydOlkWM45JwTzC+eBzX3TgHsqI13eA==} + /@openzeppelin/hardhat-upgrades/1.22.1_kt2bb34tk6drucgqtuhpnmxvru: + resolution: {integrity: sha512-MdoitCTLl4zwMU8MeE/bCj+7JMWBEvd38XqJkw36PkJrXlbv6FedDVCPoumMAhpmtymm0nTwTYYklYG+L6WiiQ==} hasBin: true peerDependencies: '@nomiclabs/hardhat-ethers': ^2.0.0 @@ -1387,8 +1360,7 @@ packages: dev: true /aes-js/3.0.0: - resolution: {integrity: sha1-4h3xCtbCBTKVvLuNq0Cwnb6ofk0=} - dev: true + resolution: {integrity: sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw==} /aes-js/3.1.2: resolution: {integrity: sha512-e5pEa2kBnBOgR4Y/p20pskXI74UEz7de8ZGVo58asOtvSVG5YAbJeELPZxOmt+Bnz3rX753YKhfIn4X4l1PPRQ==} @@ -2233,7 +2205,6 @@ packages: /bech32/1.1.4: resolution: {integrity: sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==} - dev: true /bignumber.js/9.0.2: resolution: {integrity: sha512-GAcQvbpsM0pUb0zw1EI0KhQEZ+lRwR5fYaAp3vPOYuP7aDvGy6cVN6XHLauvF8SOga2y0dcLcjt3iQDTSEliyw==} @@ -2294,7 +2265,6 @@ packages: /bn.js/4.12.0: resolution: {integrity: sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==} - dev: true /bn.js/5.2.0: resolution: {integrity: sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==} @@ -2302,7 +2272,6 @@ packages: /bn.js/5.2.1: resolution: {integrity: sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==} - dev: true /body-parser/1.19.1: resolution: {integrity: sha512-8ljfQi5eBk8EJfECMrgqNGWPEY5jWP+1IzkzkGdFFEwFQZZyaZ21UqdaHktgiMlH0xLHqIFtE/u2OYE5dOtViA==} @@ -2368,8 +2337,7 @@ packages: dev: true /brorand/1.1.0: - resolution: {integrity: sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=} - dev: true + resolution: {integrity: sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==} /browser-readablestream-to-it/1.0.3: resolution: {integrity: sha512-+12sHB+Br8HIh6VAMVEG5r3UXCyESIgDW7kzk3BjIXa43DVqVwL7GC5TW3jeh+72dtcH99pPVpw0X8i0jt+/kw==} @@ -3499,7 +3467,6 @@ packages: inherits: 2.0.4 minimalistic-assert: 1.0.1 minimalistic-crypto-utils: 1.0.1 - dev: true /emoji-regex/10.0.0: resolution: {integrity: sha512-KmJa8l6uHi1HrBI34udwlzZY1jOEuID/ft4d8BSSEdRyap7PwBEt910453PJa5MuGvxkLqlt4Uvhu7tttFHViw==} @@ -3823,7 +3790,7 @@ packages: '@codechecks/client': optional: true dependencies: - '@ethersproject/abi': 5.5.0 + '@ethersproject/abi': 5.6.4 '@solidity-parser/parser': 0.14.1 cli-table3: 0.5.1 colors: 1.4.0 @@ -4259,7 +4226,6 @@ packages: transitivePeerDependencies: - bufferutil - utf-8-validate - dev: true /ethjs-unit/0.1.6: resolution: {integrity: sha1-xmWSHkduh7ziqdWIpv4EBbLEFpk=} @@ -5285,7 +5251,6 @@ packages: dependencies: inherits: 2.0.4 minimalistic-assert: 1.0.1 - dev: true /he/1.2.0: resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} @@ -5297,12 +5262,11 @@ packages: dev: true /hmac-drbg/1.0.1: - resolution: {integrity: sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=} + resolution: {integrity: sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==} dependencies: hash.js: 1.1.7 minimalistic-assert: 1.0.1 minimalistic-crypto-utils: 1.0.1 - dev: true /home-or-tmp/2.0.0: resolution: {integrity: sha1-42w/LSyufXRqhX440Y1fMqeILbg=} @@ -5466,7 +5430,6 @@ packages: /inherits/2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - dev: true /ini/1.3.8: resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} @@ -6169,12 +6132,11 @@ packages: dev: true /js-sha3/0.5.7: - resolution: {integrity: sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc=} + resolution: {integrity: sha512-GII20kjaPX0zJ8wzkTbNDYMY7msuZcTWk8S5UOh6806Jq/wz1J8/bnr8uGU0DAUmYDjj2Mr4X1cW8v/GLYnR+g==} dev: true /js-sha3/0.8.0: resolution: {integrity: sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==} - dev: true /js-tokens/3.0.2: resolution: {integrity: sha1-mGbfOVECEw449/mWvOtlRDIJwls=} @@ -6965,11 +6927,9 @@ packages: /minimalistic-assert/1.0.1: resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} - dev: true /minimalistic-crypto-utils/1.0.1: - resolution: {integrity: sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=} - dev: true + resolution: {integrity: sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==} /minimatch/3.0.4: resolution: {integrity: sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==} @@ -8713,7 +8673,6 @@ packages: /scrypt-js/3.0.1: resolution: {integrity: sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==} - dev: true /scryptsy/1.2.1: resolution: {integrity: sha1-oyJfpLJST4AnAHYeKFW987LZIWM=} @@ -10813,7 +10772,6 @@ packages: optional: true utf-8-validate: optional: true - dev: true /ws/7.5.7: resolution: {integrity: sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A==} diff --git a/scripts/deploy-nft2.js b/scripts/deploy-nft2.js index f92a819..4df24bc 100644 --- a/scripts/deploy-nft2.js +++ b/scripts/deploy-nft2.js @@ -11,17 +11,6 @@ async function main() { const chainId = await deployUtils.currentChainId(); let [deployer] = await ethers.getSigners(); - let owner, holder, renter; - let farm, turf, validator; - let game; - let seed; - let bud; - let store; - let pool; - let gameViews; - const turfTokenType = 1; - const farmTokenType = 2; - const network = chainId === 56 ? "bsc" : chainId === 97 ? "bsc_testnet" : "localhost"; console.log("Deploying contracts with the account:", deployer.address, "to", network); diff --git a/scripts/deploy-wl.js b/scripts/deploy-wl.js index c73a5dc..1ee9d7a 100644 --- a/scripts/deploy-wl.js +++ b/scripts/deploy-wl.js @@ -12,7 +12,7 @@ async function main() { const chainId = await deployUtils.currentChainId(); let [deployer] = await ethers.getSigners(); - const network = chainId === 56 ? "bsc" : chainId === 44787 ? "alfajores" : "localhost"; + const network = chainId === 56 ? "bsc" : chainId === 5 ? "goerli" : chainId === 44787 ? "alfajores" : "localhost"; console.log("Deploying contracts with the account:", deployer.address, "to", network); console.log("Account balance:", (await deployer.getBalance()).toString()); diff --git a/scripts/exportABIs.js b/scripts/exportABIs.js index 17ce3b8..ae4bcf3 100644 --- a/scripts/exportABIs.js +++ b/scripts/exportABIs.js @@ -17,6 +17,7 @@ async function main() { abi("Farm", "tokens"); abi("Turf", "tokens"); abi("SeedTokenMock", "mocks"); + abi("GamePool", ""); await fs.writeFile(path.resolve(__dirname, "../export/ABIs.json"), JSON.stringify(ABIs, null, 2)); } diff --git a/test/Attributable.test.js b/test/Attributable.test.js index dd0f424..3e16653 100644 --- a/test/Attributable.test.js +++ b/test/Attributable.test.js @@ -1,5 +1,5 @@ const {expect, assert} = require("chai"); -const {deployContract, deployContractUpgradeable} = require("./helpers"); +const {deployContract, deployContractUpgradeable, overrideConsoleLog, restoreConsoleLog} = require("./helpers"); describe("Attributable", function () { let myPlayer; @@ -17,6 +17,11 @@ describe("Attributable", function () { before(async function () { [owner, holder] = await ethers.getSigners(); + overrideConsoleLog(); + }); + + after(async function () { + restoreConsoleLog(); }); beforeEach(async function () { diff --git a/test/FarmToken.test.js b/test/FarmToken.test.js index 2838c3b..b8ffa75 100644 --- a/test/FarmToken.test.js +++ b/test/FarmToken.test.js @@ -1,6 +1,6 @@ const {expect, assert} = require("chai"); -const {initEthers} = require("./helpers"); +const {initEthers, overrideConsoleLog, restoreConsoleLog} = require("./helpers"); // tests to be fixed @@ -8,21 +8,42 @@ describe("FarmToken", function () { let FarmToken, nft; let FarmTokenBridged, bridgedNft; let FarmMock, farm; - let owner, holder, game; + let owner, game, holder, holder2, holder3; before(async function () { - [owner, holder, game] = await ethers.getSigners(); - FarmToken = await ethers.getContractFactory("FarmTokenMock"); + [owner, game, holder, holder2, holder3] = await ethers.getSigners(); + FarmToken = await ethers.getContractFactory("Farm"); FarmMock = await ethers.getContractFactory("FarmMock"); initEthers(ethers); + overrideConsoleLog(); + }); + + after(async function () { + restoreConsoleLog(); }); async function initAndDeploy() { nft = await upgrades.deployProxy(FarmToken, ["https://meta.mob.land/farms/"]); await nft.deployed(); - + await nft.setMaxSupply(5000); + // this cannot be put in the initializer because we are testing a version + // of a contract that has been already deployed in production farm = await FarmMock.deploy(nft.address); await farm.deployed(); + await nft.setFactory(farm.address, true); + await expect(nft.setLocker(farm.address)).to.emit(nft, "LockerSet").withArgs(farm.address); + + await farm.mintTokens(holder.address, 25); + await farm.mintTokens(holder.address, 25); + await farm.mintTokens(holder.address, 25); + await farm.mintTokens(holder.address, 25); + for (let i = 1; i <= 100; i += 3) { + await nft.connect(holder).approve(farm.address, i); + } + for (let i = 1; i <= 100; i += 3) { + await expect(farm.lockToken(i)).to.emit(nft, "Locked").withArgs(i, true); + } + await expect(farm.lockToken(2)).revertedWith("LockerNotApproved()"); } describe("constructor and initialization", async function () { @@ -30,8 +51,45 @@ describe("FarmToken", function () { await initAndDeploy(); }); - it("should revert if not authorized", async function () { - await expect(await nft.isFactory(farm.address)).equal(false); + it("should emit the expected events", async function () { + await expect(nft.emitNewLockedEvent(), { + gasLimit: 300000, + }) + .to.emit(nft, "DefaultLocked") + .to.emit(nft, "Locked") + .withArgs(1, true) + .to.emit(nft, "Locked") + .withArgs(4, true) + .to.emit(nft, "Locked") + .withArgs(7, true) + .to.emit(nft, "Locked") + .withArgs(19, true) + .to.emit(nft, "Locked") + .withArgs(34, true); + }); + it("should emit the expected number of events", async function () { + // we need to stop the console capture to make this working + restoreConsoleLog(); + + let tx = await nft.emitNewLockedEvent({ + gasLimit: 300000, + }); + await tx.wait(); + let events = await nft.queryFilter(nft.filters.Locked(), tx.blockNumber); + expect(events.length).equal(14); + + tx = await nft.emitNewLockedEvent({ + gasLimit: 1000000, + }); + await tx.wait(); + events = await nft.queryFilter(nft.filters.Locked(), tx.blockNumber); + expect(events.length).equal(20); + + await expect( + nft.emitNewLockedEvent({ + gasLimit: 300000, + }) + ).revertedWith("NewLockedAlreadyEmitted()"); }); }); }); diff --git a/test/GamePool.test.js b/test/GamePool.test.js index 4f14ce8..9bec4a0 100644 --- a/test/GamePool.test.js +++ b/test/GamePool.test.js @@ -2,7 +2,16 @@ process.env.NODE_ENV = "test"; const {expect, assert} = require("chai"); const _ = require("lodash"); -const {initEthers, signPackedData, cleanStruct, randomNonce, increaseBlockTimestampBy, getTimestamp} = require("./helpers"); +const { + initEthers, + signPackedData, + cleanStruct, + randomNonce, + increaseBlockTimestampBy, + getTimestamp, + overrideConsoleLog, + restoreConsoleLog, +} = require("./helpers"); const turfAttributesJson = require("./fixtures/json/turfAttributes.json"); const farmAttributesJson = require("./fixtures/json/farmAttributes.json"); @@ -28,6 +37,11 @@ describe("GamePool", function () { before(async function () { [owner, holder, renter, buyer1, validator0, validator1, buyer2, buyer3, buyer4, buyer5] = await ethers.getSigners(); initEthers(ethers); + overrideConsoleLog(); + }); + + after(async function () { + restoreConsoleLog(); }); async function getSignature(hash, privateKey) { diff --git a/test/Integration.test.js b/test/Integration.test.js index a2ffaeb..819a5c3 100644 --- a/test/Integration.test.js +++ b/test/Integration.test.js @@ -2,10 +2,24 @@ process.env.NODE_ENV = "test"; const {expect, assert} = require("chai"); const _ = require("lodash"); -const {initEthers, signPackedData, cleanStruct, randomNonce, getTimestamp} = require("./helpers"); +const { + initEthers, + signPackedData, + cleanStruct, + randomNonce, + getTimestamp, + overrideConsoleLog, + restoreConsoleLog, +} = require("./helpers"); const turfAttributesJson = require("./fixtures/json/turfAttributes.json"); const farmAttributesJson = require("./fixtures/json/farmAttributes.json"); +// Perform your tests +// ... + +// Restore the original console.log function +// console.log = console.log.bind(console); + const DeployUtils = require("../scripts/lib/DeployUtils"); describe("Integration test", function () { @@ -27,6 +41,11 @@ describe("Integration test", function () { before(async function () { [owner, holder, renter, buyer1, validator0, validator1, buyer2, buyer3, buyer4, buyer5] = await ethers.getSigners(); initEthers(ethers); + overrideConsoleLog(); + }); + + after(async function () { + restoreConsoleLog(); }); async function getSignature(hash, privateKey) { @@ -144,8 +163,8 @@ describe("Integration test", function () { expect(await pool.getNumberOfStakes(buyer1.address, turfTokenType)).equal(0); expect(await pool.connect(buyer1).stakeAsset(turfTokenType, turfId)) - .emit(turf, "Locked") - .withArgs(turfId); + .emit(turf, "Locked(uint256,bool)") + .withArgs(turfId, true); expect(await pool.getNumberOfStakes(buyer1.address, turfTokenType)).equal(1); @@ -165,8 +184,8 @@ describe("Integration test", function () { let signature1 = getSignature(hash, validator1PK); expect(await pool.connect(buyer1).unstakeAsset(turfTokenType, turfId, stakeIndex, nonce, signature0, signature1)) - .emit(turf, "Unlocked") - .withArgs(turfId); + .emit(turf, "Locked(uint256,bool)") + .withArgs(turfId, false); nonce = randomNonce(); hash = await pool.hashUnstake(farmTokenType, farmId, stakeIndex, nonce); @@ -174,8 +193,8 @@ describe("Integration test", function () { signature1 = getSignature(hash, validator1PK); expect(await pool.connect(buyer1).unstakeAsset(farmTokenType, farmId, stakeIndex, nonce, signature0, signature1)) - .emit(farm, "Unlocked") - .withArgs(farmId); + .emit(farm, "Locked(uint256,bool)") + .withArgs(farmId, false); expect((await pool.getStakeByIndex(buyer1.address, turfTokenType, 0)).unlockedAt).greaterThan(0); diff --git a/test/NftFactory.test.js b/test/NftFactory.test.js index 7f552b5..4503d22 100644 --- a/test/NftFactory.test.js +++ b/test/NftFactory.test.js @@ -1,6 +1,13 @@ const {expect, assert} = require("chai"); -const {initEthers, increaseBlockTimestampBy, cleanStruct, getTimestamp} = require("./helpers"); +const { + initEthers, + increaseBlockTimestampBy, + cleanStruct, + getTimestamp, + overrideConsoleLog, + restoreConsoleLog, +} = require("./helpers"); const DeployUtils = require("../scripts/lib/DeployUtils"); // tests to be fixed @@ -29,6 +36,11 @@ describe("NftFactory", function () { FarmToken = await ethers.getContractFactory("Farm"); NftFactory = await ethers.getContractFactory("NftFactory"); initEthers(ethers); + overrideConsoleLog(); + }); + + after(async function () { + restoreConsoleLog(); }); async function initAndDeploy(configure) { diff --git a/test/TurfToken.test.js b/test/TurfToken.test.js index be9eb0d..6925a91 100644 --- a/test/TurfToken.test.js +++ b/test/TurfToken.test.js @@ -1,6 +1,6 @@ const {expect, assert} = require("chai"); -const {initEthers} = require("./helpers"); +const {initEthers, overrideConsoleLog, restoreConsoleLog} = require("./helpers"); // tests to be fixed @@ -17,6 +17,11 @@ describe("TurfToken", function () { FarmMock = await ethers.getContractFactory("FarmMock"); initEthers(ethers); + overrideConsoleLog(); + }); + + after(async function () { + restoreConsoleLog(); }); async function initAndDeploy() { diff --git a/test/WhiteListSlot.test.js b/test/WhiteListSlot.test.js index ec8acc6..c28190a 100644 --- a/test/WhiteListSlot.test.js +++ b/test/WhiteListSlot.test.js @@ -1,6 +1,6 @@ const {expect, assert} = require("chai"); -const {initEthers} = require("./helpers"); +const {initEthers, overrideConsoleLog, restoreConsoleLog} = require("./helpers"); // tests to be fixed @@ -15,6 +15,11 @@ describe("WhiteList", function () { BurnerMock = await ethers.getContractFactory("BurnerMock"); initEthers(ethers); + overrideConsoleLog(); + }); + + after(async function () { + restoreConsoleLog(); }); async function initAndDeploy() { diff --git a/test/helpers.js b/test/helpers.js index afeeee2..78f7f24 100644 --- a/test/helpers.js +++ b/test/helpers.js @@ -1,10 +1,28 @@ const {assert} = require("chai"); +let originalConsoleLog; + const Helpers = { initEthers(ethers) { this.ethers = ethers; }, + overrideConsoleLog() { + originalConsoleLog = console.log; + + const log = (msg) => { + if (/Duplicate definition of/.test(msg)) { + return; + } + originalConsoleLog(msg); + }; + console.log = log; + }, + + restoreConsoleLog() { + console.log = originalConsoleLog; + }, + async assertThrowsMessage(promise, message) { try { await promise; diff --git a/verified-sources/placeholder b/verified-sources/placeholder new file mode 100644 index 0000000..3b94f91 --- /dev/null +++ b/verified-sources/placeholder @@ -0,0 +1 @@ +Placeholder