From 761c724438ddf8f7d2066f1b8805d02e5c5879de Mon Sep 17 00:00:00 2001 From: Giovanni Sanchez <108043524+sisyphusSmiling@users.noreply.github.com> Date: Thu, 31 Oct 2024 14:01:23 -0600 Subject: [PATCH 01/20] forge install: random-coin-toss --- .gitmodules | 3 +++ solidity/lib/random-coin-toss | 1 + 2 files changed, 4 insertions(+) create mode 160000 solidity/lib/random-coin-toss diff --git a/.gitmodules b/.gitmodules index 0254bef..9af280a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,3 +7,6 @@ [submodule "solidity/lib/forge-std"] path = solidity/lib/forge-std url = https://github.com/foundry-rs/forge-std +[submodule "solidity/lib/random-coin-toss"] + path = solidity/lib/random-coin-toss + url = https://github.com/onflow/random-coin-toss diff --git a/solidity/lib/random-coin-toss b/solidity/lib/random-coin-toss new file mode 160000 index 0000000..8d47d83 --- /dev/null +++ b/solidity/lib/random-coin-toss @@ -0,0 +1 @@ +Subproject commit 8d47d83772f0f8e225cdc2cb8fc61706731b0712 From 9f2a8de17484ec25b16de6dfd31fa7c094d0c521 Mon Sep 17 00:00:00 2001 From: Giovanni Sanchez <108043524+sisyphusSmiling@users.noreply.github.com> Date: Thu, 31 Oct 2024 14:30:48 -0600 Subject: [PATCH 02/20] remove submodule --- .gitmodules | 5 +---- solidity/lib/random-coin-toss | 1 - 2 files changed, 1 insertion(+), 5 deletions(-) delete mode 160000 solidity/lib/random-coin-toss diff --git a/.gitmodules b/.gitmodules index 9af280a..c4b9ae2 100644 --- a/.gitmodules +++ b/.gitmodules @@ -6,7 +6,4 @@ url = https://github.com/foundry-rs/forge-std [submodule "solidity/lib/forge-std"] path = solidity/lib/forge-std - url = https://github.com/foundry-rs/forge-std -[submodule "solidity/lib/random-coin-toss"] - path = solidity/lib/random-coin-toss - url = https://github.com/onflow/random-coin-toss + url = https://github.com/foundry-rs/forge-std \ No newline at end of file diff --git a/solidity/lib/random-coin-toss b/solidity/lib/random-coin-toss deleted file mode 160000 index 8d47d83..0000000 --- a/solidity/lib/random-coin-toss +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 8d47d83772f0f8e225cdc2cb8fc61706731b0712 From f0453d2fbd1b95925c73ac9ca8772ce906bbfce7 Mon Sep 17 00:00:00 2001 From: Giovanni Sanchez <108043524+sisyphusSmiling@users.noreply.github.com> Date: Thu, 31 Oct 2024 14:30:55 -0600 Subject: [PATCH 03/20] forge install: random-coin-toss --- .gitmodules | 5 ++++- solidity/lib/random-coin-toss | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) create mode 160000 solidity/lib/random-coin-toss diff --git a/.gitmodules b/.gitmodules index c4b9ae2..9af280a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -6,4 +6,7 @@ url = https://github.com/foundry-rs/forge-std [submodule "solidity/lib/forge-std"] path = solidity/lib/forge-std - url = https://github.com/foundry-rs/forge-std \ No newline at end of file + url = https://github.com/foundry-rs/forge-std +[submodule "solidity/lib/random-coin-toss"] + path = solidity/lib/random-coin-toss + url = https://github.com/onflow/random-coin-toss diff --git a/solidity/lib/random-coin-toss b/solidity/lib/random-coin-toss new file mode 160000 index 0000000..8d47d83 --- /dev/null +++ b/solidity/lib/random-coin-toss @@ -0,0 +1 @@ +Subproject commit 8d47d83772f0f8e225cdc2cb8fc61706731b0712 From 8f6e417c3c32c9dd1d69a15adabaa33b5431e2d6 Mon Sep 17 00:00:00 2001 From: Giovanni Sanchez <108043524+sisyphusSmiling@users.noreply.github.com> Date: Thu, 31 Oct 2024 17:07:21 -0600 Subject: [PATCH 04/20] update foundry.toml --- foundry.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/foundry.toml b/foundry.toml index 2b5e79b..755773f 100644 --- a/foundry.toml +++ b/foundry.toml @@ -4,5 +4,6 @@ out = "./solidity/out" libs = ["./solidity/lib"] script = "./solidity/script" test = "./solidity/test" +cache_path = "./solidity/cache" # See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options From a37c4173018d18301ba145a25c3abba15549c4e2 Mon Sep 17 00:00:00 2001 From: Giovanni Sanchez <108043524+sisyphusSmiling@users.noreply.github.com> Date: Thu, 31 Oct 2024 17:08:00 -0600 Subject: [PATCH 05/20] update foundry remappings --- remappings.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/remappings.txt b/remappings.txt index 6c3e85d..5776ef6 100644 --- a/remappings.txt +++ b/remappings.txt @@ -3,3 +3,4 @@ ds-test/=solidity/lib/forge-std/lib/ds-test/src/ erc4626-tests/=solidity/lib/openzeppelin-contracts/lib/erc4626-tests/ forge-std/=solidity/lib/forge-std/src/ openzeppelin-contracts/=solidity/lib/openzeppelin-contracts/ +onflow/random-coin-toss=solidity/lib/random-coin-toss \ No newline at end of file From 161e07b9da37163453dbaf9e11c2163c6dece430 Mon Sep 17 00:00:00 2001 From: Giovanni Sanchez <108043524+sisyphusSmiling@users.noreply.github.com> Date: Fri, 1 Nov 2024 12:41:19 -0600 Subject: [PATCH 06/20] add CadenceArchUtils library & test coverage on random mint --- solidity/src/CadenceArchUtils.sol | 57 +++++++++++++++++++++++++++++ solidity/src/MaybeMintERC721.sol | 25 ++++++++++++- solidity/test/MaybeMintERC721.t.sol | 31 +++++++++++++++- 3 files changed, 110 insertions(+), 3 deletions(-) create mode 100644 solidity/src/CadenceArchUtils.sol diff --git a/solidity/src/CadenceArchUtils.sol b/solidity/src/CadenceArchUtils.sol new file mode 100644 index 0000000..e094395 --- /dev/null +++ b/solidity/src/CadenceArchUtils.sol @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +/** + * @dev This contract is a base contract to facilitate easier consumption of the Cadence Arch pre-compiles. Implementing + * contracts can use this contract to fetch the current Flow block height and fetch random numbers from the Cadence + * runtime. + */ +library CadenceArchUtils { + // Cadence Arch pre-compile address + address public constant cadenceArch = 0x0000000000000000000000010000000000000001; + + /** + * @dev This method returns the current Flow block height. + * + * @return flowBlockHeight The current Flow block height. + */ + function _flowBlockHeight() internal view returns (uint64) { + (bool ok, bytes memory data) = cadenceArch.staticcall(abi.encodeWithSignature("flowBlockHeight()")); + require(ok, "Unsuccessful call to Cadence Arch pre-compile when fetching Flow block height"); + + uint64 output = abi.decode(data, (uint64)); + return output; + } + + /** + * @dev This method uses the Cadence Arch pre-compiles to return a random number from the Cadence runtime. Consumers + * should know this is a revertible random source and should only be used as a source of randomness when called by + * trusted callers - i.e. with trust that the caller won't revert on result. + * + * @return randomSource The random source. + */ + function _revertibleRandom() internal view returns (uint64) { + (bool ok, bytes memory data) = cadenceArch.staticcall(abi.encodeWithSignature("revertibleRandom()")); + require(ok, "Unsuccessful call to Cadence Arch pre-compile when fetching revertible random number"); + + uint64 output = abi.decode(data, (uint64)); + return output; + } + + /** + * @dev This method uses the Cadence Arch pre-compiles to returns a random source for a given Flow block height. + * The provided height must be at least one block in the past. + * + * @param flowHeight The Flow block height for which to get the random source. + * @return randomSource The random source for the given Flow block height. + */ + function _getRandomSource(uint64 flowHeight) internal view returns (bytes32) { + (bool ok, bytes memory data) = + cadenceArch.staticcall(abi.encodeWithSignature("getRandomSource(uint64)", flowHeight)); + require(ok, "Unsuccessful call to Cadence Arch pre-compile when fetching random source"); + + // Decode the result as bytes32 & return + bytes32 result = abi.decode(data, (bytes32)); + return result; + } +} diff --git a/solidity/src/MaybeMintERC721.sol b/solidity/src/MaybeMintERC721.sol index 0906222..fe1c981 100644 --- a/solidity/src/MaybeMintERC721.sol +++ b/solidity/src/MaybeMintERC721.sol @@ -3,6 +3,8 @@ pragma solidity 0.8.24; import {ERC721} from "@openzeppelin/contracts/token/ERC721/ERC721.sol"; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; +import {CadenceArchUtils} from "./CadenceArchUtils.sol"; +// import {CadenceArchUtils} from "onflow/random-coin-toss/solidity/src/CadenceArchUtils.sol"; /** * @title MaybeMintERC721 @@ -36,10 +38,29 @@ contract MaybeMintERC721 is ERC721, Ownable { * to the beneficiary before minting the ERC721 to pay for mint */ function mint() external { - // TODO: Get a random number to determine if the mint is successful - // TODO: Set token URI + // Randomly fail mint with 50% chance of reverting + _maybeMint(); + } + + /** + * @dev Mint a new ERC721 token to the caller with some chance of failure. + * NOTE: Production systems using random minting should leverage a commit-reveal scheme + * to ensure that the random minting transaction cannot be reverted on random result. + */ + function _maybeMint() internal { + _splitChanceRevert(); // randomly revert with 50% chance + totalSupply++; // increment the total supply denomination.transferFrom(msg.sender, beneficiary, mintCost); // take payment for mint _mint(msg.sender, totalSupply); // mint the token, assigning the next tokenId + // TODO: Set token URI + } + + /** + * @dev Randomly revert with 50% chance + */ + function _splitChanceRevert() internal view { + uint64 random = CadenceArchUtils._revertibleRandom(); + require(random % 2 == 0, "No mint for you!"); } } diff --git a/solidity/test/MaybeMintERC721.t.sol b/solidity/test/MaybeMintERC721.t.sol index b1b2f9d..b4b0694 100644 --- a/solidity/test/MaybeMintERC721.t.sol +++ b/solidity/test/MaybeMintERC721.t.sol @@ -8,6 +8,9 @@ import {MaybeMintERC721} from "../src/MaybeMintERC721.sol"; import {ExampleERC20} from "../src/test/ExampleERC20.sol"; contract MaybeMintERC721Test is Test { + // Cadence Arch pre-compile address used to get onchain revertible randomness + address private cadenceArch = 0x0000000000000000000000010000000000000001; + // Contracts MaybeMintERC721 private erc721; ExampleERC20 private erc20; @@ -28,15 +31,41 @@ contract MaybeMintERC721Test is Test { erc721 = new MaybeMintERC721(name, symbol, address(erc20), mintCost, beneficiary); } - function test_mint() public { + function testMintRandomEvenSucceeds() public { erc20.mint(user, mintCost); // mint ERC20 to user vm.prank(user); erc20.approve(address(erc721), mintCost); // approve the ERC20 to be spent by MaybeMintERC721 + // Mock the Cadence Arch precompile for revertibleRandom() call, returning 0 - mint should succeed + vm.mockCall(cadenceArch, abi.encodeWithSignature("revertibleRandom()"), abi.encode(uint64(0))); + vm.prank(user); erc721.mint(); // mint ERC721 to user assertEq(erc721.ownerOf(1), user); // user should own the ERC721 token } + + function testMintRandomOddFails() public { + erc20.mint(user, mintCost); // mint ERC20 to user + + vm.prank(user); + erc20.approve(address(erc721), mintCost); // approve the ERC20 to be spent by MaybeMintERC721 + + // Mock the Cadence Arch precompile for revertibleRandom() call, returning 1 - mint should fail + vm.mockCall(cadenceArch, abi.encodeWithSignature("revertibleRandom()"), abi.encode(uint64(3))); + + vm.prank(user); + vm.expectRevert("No mint for you!"); + erc721.mint(); // Attempt to mint ERC721 to user - should revert + } + + function testMintRandomWithoutApproveFails() public { + // Mock the Cadence Arch precompile for revertibleRandom() call, returning 0 - allows mint + vm.mockCall(cadenceArch, abi.encodeWithSignature("revertibleRandom()"), abi.encode(uint64(0))); + + vm.prank(user); + vm.expectRevert(); + erc721.mint(); // Attempt to mint ERC721 to user - reverts as user has not approved ERC20 + } } From 5976256363ef9e57072559c3aa8613ab8a390bc9 Mon Sep 17 00:00:00 2001 From: Giovanni Sanchez <108043524+sisyphusSmiling@users.noreply.github.com> Date: Fri, 1 Nov 2024 14:31:39 -0600 Subject: [PATCH 07/20] update dependencies --- solidity/lib/openzeppelin-contracts | 2 +- solidity/lib/random-coin-toss | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/solidity/lib/openzeppelin-contracts b/solidity/lib/openzeppelin-contracts index 69c8def..448efee 160000 --- a/solidity/lib/openzeppelin-contracts +++ b/solidity/lib/openzeppelin-contracts @@ -1 +1 @@ -Subproject commit 69c8def5f222ff96f2b5beff05dfba996368aa79 +Subproject commit 448efeea6640bbbc09373f03fbc9c88e280147ba diff --git a/solidity/lib/random-coin-toss b/solidity/lib/random-coin-toss index 8d47d83..e82dee9 160000 --- a/solidity/lib/random-coin-toss +++ b/solidity/lib/random-coin-toss @@ -1 +1 @@ -Subproject commit 8d47d83772f0f8e225cdc2cb8fc61706731b0712 +Subproject commit e82dee9bab346049532ef0fd3574037f391e6428 From c73ef703353c6184f3c6a92316026d7d72a25d81 Mon Sep 17 00:00:00 2001 From: Giovanni Sanchez <108043524+sisyphusSmiling@users.noreply.github.com> Date: Fri, 1 Nov 2024 14:46:13 -0600 Subject: [PATCH 08/20] replace local dep with foundry installed dep --- solidity/src/CadenceArchUtils.sol | 57 ------------------------------- solidity/src/MaybeMintERC721.sol | 3 +- 2 files changed, 1 insertion(+), 59 deletions(-) delete mode 100644 solidity/src/CadenceArchUtils.sol diff --git a/solidity/src/CadenceArchUtils.sol b/solidity/src/CadenceArchUtils.sol deleted file mode 100644 index e094395..0000000 --- a/solidity/src/CadenceArchUtils.sol +++ /dev/null @@ -1,57 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -/** - * @dev This contract is a base contract to facilitate easier consumption of the Cadence Arch pre-compiles. Implementing - * contracts can use this contract to fetch the current Flow block height and fetch random numbers from the Cadence - * runtime. - */ -library CadenceArchUtils { - // Cadence Arch pre-compile address - address public constant cadenceArch = 0x0000000000000000000000010000000000000001; - - /** - * @dev This method returns the current Flow block height. - * - * @return flowBlockHeight The current Flow block height. - */ - function _flowBlockHeight() internal view returns (uint64) { - (bool ok, bytes memory data) = cadenceArch.staticcall(abi.encodeWithSignature("flowBlockHeight()")); - require(ok, "Unsuccessful call to Cadence Arch pre-compile when fetching Flow block height"); - - uint64 output = abi.decode(data, (uint64)); - return output; - } - - /** - * @dev This method uses the Cadence Arch pre-compiles to return a random number from the Cadence runtime. Consumers - * should know this is a revertible random source and should only be used as a source of randomness when called by - * trusted callers - i.e. with trust that the caller won't revert on result. - * - * @return randomSource The random source. - */ - function _revertibleRandom() internal view returns (uint64) { - (bool ok, bytes memory data) = cadenceArch.staticcall(abi.encodeWithSignature("revertibleRandom()")); - require(ok, "Unsuccessful call to Cadence Arch pre-compile when fetching revertible random number"); - - uint64 output = abi.decode(data, (uint64)); - return output; - } - - /** - * @dev This method uses the Cadence Arch pre-compiles to returns a random source for a given Flow block height. - * The provided height must be at least one block in the past. - * - * @param flowHeight The Flow block height for which to get the random source. - * @return randomSource The random source for the given Flow block height. - */ - function _getRandomSource(uint64 flowHeight) internal view returns (bytes32) { - (bool ok, bytes memory data) = - cadenceArch.staticcall(abi.encodeWithSignature("getRandomSource(uint64)", flowHeight)); - require(ok, "Unsuccessful call to Cadence Arch pre-compile when fetching random source"); - - // Decode the result as bytes32 & return - bytes32 result = abi.decode(data, (bytes32)); - return result; - } -} diff --git a/solidity/src/MaybeMintERC721.sol b/solidity/src/MaybeMintERC721.sol index fe1c981..47c0620 100644 --- a/solidity/src/MaybeMintERC721.sol +++ b/solidity/src/MaybeMintERC721.sol @@ -3,8 +3,7 @@ pragma solidity 0.8.24; import {ERC721} from "@openzeppelin/contracts/token/ERC721/ERC721.sol"; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; -import {CadenceArchUtils} from "./CadenceArchUtils.sol"; -// import {CadenceArchUtils} from "onflow/random-coin-toss/solidity/src/CadenceArchUtils.sol"; +import {CadenceArchUtils} from "onflow/random-coin-toss/solidity/src/CadenceArchUtils.sol"; /** * @title MaybeMintERC721 From aa01cbb9dc80d91d5a0330a1a6f429a20d740a22 Mon Sep 17 00:00:00 2001 From: Giovanni Sanchez <108043524+sisyphusSmiling@users.noreply.github.com> Date: Mon, 4 Nov 2024 11:33:48 -0700 Subject: [PATCH 09/20] add custom errors to ERC721 --- solidity/src/MaybeMintERC721.sol | 19 +- solidity/src/test/WETH9.sol | 756 ++++++++++++++++++++++++++++ solidity/test/MaybeMintERC721.t.sol | 5 +- 3 files changed, 773 insertions(+), 7 deletions(-) create mode 100644 solidity/src/test/WETH9.sol diff --git a/solidity/src/MaybeMintERC721.sol b/solidity/src/MaybeMintERC721.sol index 47c0620..3d98c1a 100644 --- a/solidity/src/MaybeMintERC721.sol +++ b/solidity/src/MaybeMintERC721.sol @@ -17,6 +17,9 @@ contract MaybeMintERC721 is ERC721, Ownable { address public beneficiary; uint256 public totalSupply; + error RandomRevert(); + error InsufficientAllowance(address denomination, address sender, uint256 needed); + constructor(string memory _name, string memory _symbol, address _erc20, uint256 _mintCost, address _beneficiary) ERC721(_name, _symbol) Ownable(msg.sender) @@ -49,10 +52,14 @@ contract MaybeMintERC721 is ERC721, Ownable { function _maybeMint() internal { _splitChanceRevert(); // randomly revert with 50% chance - totalSupply++; // increment the total supply - denomination.transferFrom(msg.sender, beneficiary, mintCost); // take payment for mint - _mint(msg.sender, totalSupply); // mint the token, assigning the next tokenId - // TODO: Set token URI + // take payment for mint + try denomination.transferFrom(msg.sender, beneficiary, mintCost) { + totalSupply++; // increment the total supply + _mint(msg.sender, totalSupply); // mint the token, assigning the next tokenId + // TODO: Set token URI + } catch { + revert InsufficientAllowance(address(denomination), msg.sender, mintCost); + } } /** @@ -60,6 +67,8 @@ contract MaybeMintERC721 is ERC721, Ownable { */ function _splitChanceRevert() internal view { uint64 random = CadenceArchUtils._revertibleRandom(); - require(random % 2 == 0, "No mint for you!"); + if (random % 2 == 1) { + revert RandomRevert(); + } } } diff --git a/solidity/src/test/WETH9.sol b/solidity/src/test/WETH9.sol new file mode 100644 index 0000000..a592dc0 --- /dev/null +++ b/solidity/src/test/WETH9.sol @@ -0,0 +1,756 @@ +// Copyright (C) 2015, 2016, 2017 Dapphub + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +pragma solidity >=0.4.22 <0.6; + +contract WETH9 { + string public name = "Wrapped Flow"; + string public symbol = "WFLOW"; + uint8 public decimals = 18; + + event Approval(address indexed src, address indexed guy, uint wad); + event Transfer(address indexed src, address indexed dst, uint wad); + event Deposit(address indexed dst, uint wad); + event Withdrawal(address indexed src, uint wad); + + mapping (address => uint) public balanceOf; + mapping (address => mapping (address => uint)) public allowance; + + function() external payable { + deposit(); + } + function deposit() public payable { + balanceOf[msg.sender] += msg.value; + emit Deposit(msg.sender, msg.value); + } + function withdraw(uint wad) public { + require(balanceOf[msg.sender] >= wad); + balanceOf[msg.sender] -= wad; + msg.sender.transfer(wad); + emit Withdrawal(msg.sender, wad); + } + + function totalSupply() public view returns (uint) { + return address(this).balance; + } + + function approve(address guy, uint wad) public returns (bool) { + allowance[msg.sender][guy] = wad; + emit Approval(msg.sender, guy, wad); + return true; + } + + function transfer(address dst, uint wad) public returns (bool) { + return transferFrom(msg.sender, dst, wad); + } + + function transferFrom(address src, address dst, uint wad) + public + returns (bool) + { + require(balanceOf[src] >= wad); + + if (src != msg.sender && allowance[src][msg.sender] != uint(-1)) { + require(allowance[src][msg.sender] >= wad); + allowance[src][msg.sender] -= wad; + } + + balanceOf[src] -= wad; + balanceOf[dst] += wad; + + emit Transfer(src, dst, wad); + + return true; + } +} + + +/* + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. + +*/ \ No newline at end of file diff --git a/solidity/test/MaybeMintERC721.t.sol b/solidity/test/MaybeMintERC721.t.sol index b4b0694..ef9bc03 100644 --- a/solidity/test/MaybeMintERC721.t.sol +++ b/solidity/test/MaybeMintERC721.t.sol @@ -56,7 +56,7 @@ contract MaybeMintERC721Test is Test { vm.mockCall(cadenceArch, abi.encodeWithSignature("revertibleRandom()"), abi.encode(uint64(3))); vm.prank(user); - vm.expectRevert("No mint for you!"); + vm.expectRevert(bytes4(keccak256("RandomRevert()"))); erc721.mint(); // Attempt to mint ERC721 to user - should revert } @@ -64,8 +64,9 @@ contract MaybeMintERC721Test is Test { // Mock the Cadence Arch precompile for revertibleRandom() call, returning 0 - allows mint vm.mockCall(cadenceArch, abi.encodeWithSignature("revertibleRandom()"), abi.encode(uint64(0))); + bytes4 errSelector = bytes4(keccak256("InsufficientAllowance(address,address,uint256)")); vm.prank(user); - vm.expectRevert(); + vm.expectRevert(abi.encodeWithSelector(errSelector, address(erc20), user, mintCost)); erc721.mint(); // Attempt to mint ERC721 to user - reverts as user has not approved ERC20 } } From 6ded160cb91e412bbf07a1ae1585804560c8056f Mon Sep 17 00:00:00 2001 From: Giovanni Sanchez <108043524+sisyphusSmiling@users.noreply.github.com> Date: Mon, 4 Nov 2024 16:19:10 -0700 Subject: [PATCH 10/20] add bundled Cadence txn --- .../transactions/bundled/wrap_and_mint.cdc | 126 ++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 cadence/transactions/bundled/wrap_and_mint.cdc diff --git a/cadence/transactions/bundled/wrap_and_mint.cdc b/cadence/transactions/bundled/wrap_and_mint.cdc new file mode 100644 index 0000000..38e07b6 --- /dev/null +++ b/cadence/transactions/bundled/wrap_and_mint.cdc @@ -0,0 +1,126 @@ +import "FungibleToken" +import "FlowToken" +import "EVM" + +/// This transaction wraps FLOW as WFLOW, approves an ERC721 contract to move the mint amount, and attempts to mint an +/// ERC721 token. The transaction is reverted if any of the EVM interactions fail +/// +transaction(wflowAddressHex: String, maybeMintERC721AddressHex: String) { + + let coa: auth(EVM.Call) &EVM.CadenceOwnedAccount + let mintCost: UFix64 + let wflowAddress: EVM.EVMAddress + let erc721Address: EVM.EVMAddress + + prepare(signer: auth(SaveValue, BorrowValue, IssueStorageCapabilityController, PublishCapability, UnpublishCapability) &Account) { + /* COA configuration & assigment */ + // + let storagePath = /storage/evm + let publicPath = /public/evm + // Configure a COA if one is not found in storage at the default path + if signer.storage.type(at: storagePath) == nil { + // Create & save the CadenceOwnedAccount (COA) Resource + let newCOA <- EVM.createCadenceOwnedAccount() + signer.storage.save(<-newCOA, to: storagePath) + + // Unpublish any existing Capability at the public path if it exists + signer.capabilities.unpublish(publicPath) + // Issue & publish the public, unentitled COA Capability + let coaCapability = signer.capabilities.storage.issue<&EVM.CadenceOwnedAccount>(storagePath) + signer.capabilities.publish(coaCapability, at: publicPath) + } + + // Assign the COA reference to the transaction's coa field + self.coa = signer.storage.borrow(from: storagePath) + ?? panic("A CadenceOwnedAccount (COA) Resource could not be found at path ".concat(storagePath.toString()) + .concat(" - ensure the COA Resource is created and saved at this path to enable EVM interactions")) + + /* Fund COA with cost of mint */ + // + // Borrow authorized reference to signer's FlowToken Vault + let sourceVault = signer.storage.borrow( + from: /storage/flowTokenVault + ) ?? panic("The signer does not store a FlowToken Vault object at the path " + .concat("/storage/flowTokenVault. ") + .concat("The signer must initialize their account with this vault first!")) + // Withdraw from the signer's FlowToken Vault + self.mintCost = 1.0 + let fundingVault <- sourceVault.withdraw(amount: self.mintCost) as! @FlowToken.Vault + // Deposit the mint cost into the COA + self.coa.deposit(from: <-fundingVault) + + /* Set the WFLOW contract address */ + // + // View the cannonical WFLOW contract at: + // https://evm-testnet.flowscan.io/address/0xd3bF53DAC106A0290B0483EcBC89d40FcC961f3e + self.wflowAddress = EVM.addressFromString(wflowAddressHex) + + /* Assign the ERC721 EVM Address */ + // + // Deserialize the provided ERC721 hex string to an EVM address + self.erc721Address = EVM.addressFromString(maybeMintERC721AddressHex) + } + + pre { + self.coa.balance().inFLOW() >= self.mintCost: + "CadenceOwnedAccount holds insufficient FLOW balance to mint - " + .concat("Ensure COA has at least ".concat(self.mintCost.toString()).concat(" FLOW")) + } + + execute { + /* Wrap FLOW in EVM as WFLOW */ + // + // Encode calldata & set value + let depositCalldata = EVM.encodeABIWithSignature("deposit()", []) + let value = EVM.Balance(attoflow: 0) + value.setFLOW(flow: self.mintCost) + // Call the WFLOW contract, wrapping the sent FLOW + let wrapResult = self.coa.call( + to: self.wflowAddress, + data: depositCalldata, + gasLimit: 15_000_000, + value: value + ) + assert( + wrapResult.status == EVM.Status.successful, + message: "Wrapping FLOW as WFLOW failed: ".concat(wrapResult.errorMessage) + ) + + /* Approve the ERC721 address for the mint amount */ + // + // Encode calldata approve(address,uint) calldata, providing the ERC721 address & mint amount + let approveCalldata = EVM.encodeABIWithSignature( + "approve(address,uint256)", + [self.erc721Address, UInt256(1_000_000_000_000_000_000)] + ) + // Call the WFLOW contract, approving the ERC721 address to move the mint amount + let approveResult = self.coa.call( + to: self.wflowAddress, + data: approveCalldata, + gasLimit: 15_000_000, + value: EVM.Balance(attoflow: 0) + ) + assert( + approveResult.status == EVM.Status.successful, + message: "Approving ERC721 address on WFLOW contract failed: ".concat(approveResult.errorMessage) + ) + + /* Attempt to mint ERC721 */ + // + // Encode the mint() calldata + let mintCalldata = EVM.encodeABIWithSignature("mint()", []) + // Call the ERC721 contract, attempting to mint + let mintResult = self.coa.call( + to: self.erc721Address, + data: mintCalldata, + gasLimit: 15_000_000, + value: EVM.Balance(attoflow: 0) + ) + // If mint fails, all other actions in this transaction are reverted + assert( + mintResult.status == EVM.Status.successful, + message: "Minting ERC721 token failed: ".concat(mintResult.errorMessage) + ) + } +} + \ No newline at end of file From 54b4550bc49547390036633db592544e8dc96dcb Mon Sep 17 00:00:00 2001 From: Giovanni Sanchez <108043524+sisyphusSmiling@users.noreply.github.com> Date: Mon, 4 Nov 2024 16:28:55 -0700 Subject: [PATCH 11/20] add stepwise Cadence txns --- .../transactions/stepwise/0_create_coa.cdc | 62 +++++++++++++++++ cadence/transactions/stepwise/1_wrap_flow.cdc | 68 +++++++++++++++++++ cadence/transactions/stepwise/2_approve.cdc | 66 ++++++++++++++++++ cadence/transactions/stepwise/3_mint.cdc | 46 +++++++++++++ 4 files changed, 242 insertions(+) create mode 100644 cadence/transactions/stepwise/0_create_coa.cdc create mode 100644 cadence/transactions/stepwise/1_wrap_flow.cdc create mode 100644 cadence/transactions/stepwise/2_approve.cdc create mode 100644 cadence/transactions/stepwise/3_mint.cdc diff --git a/cadence/transactions/stepwise/0_create_coa.cdc b/cadence/transactions/stepwise/0_create_coa.cdc new file mode 100644 index 0000000..77f8575 --- /dev/null +++ b/cadence/transactions/stepwise/0_create_coa.cdc @@ -0,0 +1,62 @@ +import "FungibleToken" +import "FlowToken" +import "EVM" + +/// Creates a CadenceOwnedAccount & funds with the specified amount. If the COA already exists, the transaction reverts. +/// +transaction(amount: UFix64) { + + let coa: auth(EVM.Call) &EVM.CadenceOwnedAccount + let fundingVault: @FlowToken.Vault + + prepare(signer: auth(SaveValue, BorrowValue, IssueStorageCapabilityController, PublishCapability, UnpublishCapability) &Account) { + pre { + amount > 0.0: "The funding amount must be greater than zero" + } + /* COA configuration & assigment */ + // + let storagePath = /storage/evm + let publicPath = /public/evm + // Configure a COA if one is not found in storage at the default path + if signer.storage.type(at: storagePath) != nil { + panic("CadenceOwnedAccount already exists at path ".concat(storagePath.toString())) + } + // Create & save the CadenceOwnedAccount (COA) Resource + let newCOA <- EVM.createCadenceOwnedAccount() + signer.storage.save(<-newCOA, to: storagePath) + + // Unpublish any existing Capability at the public path if it exists + signer.capabilities.unpublish(publicPath) + // Issue & publish the public, unentitled COA Capability + let coaCapability = signer.capabilities.storage.issue<&EVM.CadenceOwnedAccount>(storagePath) + signer.capabilities.publish(coaCapability, at: publicPath) + + // Assign the COA reference to the transaction's coa field + self.coa = signer.storage.borrow(from: storagePath) + ?? panic("A CadenceOwnedAccount (COA) Resource could not be found at path ".concat(storagePath.toString()) + .concat(" - ensure the COA Resource is created and saved at this path to enable EVM interactions")) + + // Borrow authorized reference to signer's FlowToken Vault + let sourceVault = signer.storage.borrow( + from: /storage/flowTokenVault + ) ?? panic("The signer does not store a FlowToken Vault object at the path " + .concat("/storage/flowTokenVault. ") + .concat("The signer must initialize their account with this vault first!")) + // Withdraw from the signer's FlowToken Vault + self.fundingVault <- sourceVault.withdraw(amount: amount) as! @FlowToken.Vault + } + + pre { + self.fundingVault.balance == amount: + "Expected amount =".concat(amount.toString()) + .concat(" but fundingVault.balance=").concat(self.fundingVault.balance.toString()) + } + + execute { + /* Fund COA */ + // + // Deposit the FLOW into the COA + self.coa.deposit(from: <-self.fundingVault) + } +} + \ No newline at end of file diff --git a/cadence/transactions/stepwise/1_wrap_flow.cdc b/cadence/transactions/stepwise/1_wrap_flow.cdc new file mode 100644 index 0000000..ab19d56 --- /dev/null +++ b/cadence/transactions/stepwise/1_wrap_flow.cdc @@ -0,0 +1,68 @@ +import "FungibleToken" +import "FlowToken" +import "EVM" + +/// This transaction wraps FLOW as WFLOW, funing the signer's CadenceOwnedAccount with the mint cost +/// +transaction(wflowAddressHex: String) { + + let coa: auth(EVM.Call) &EVM.CadenceOwnedAccount + let mintCost: UFix64 + let wflowAddress: EVM.EVMAddress + + prepare(signer: auth(SaveValue, BorrowValue) &Account) { + /* COA configuration & assigment */ + // + let storagePath = /storage/evm + // Assign the COA reference to the transaction's coa field + self.coa = signer.storage.borrow(from: storagePath) + ?? panic("A CadenceOwnedAccount (COA) Resource could not be found at path ".concat(storagePath.toString()) + .concat(" - ensure the COA Resource is created and saved at this path to enable EVM interactions")) + + /* Fund COA with cost of mint */ + // + // Borrow authorized reference to signer's FlowToken Vault + let sourceVault = signer.storage.borrow( + from: /storage/flowTokenVault + ) ?? panic("The signer does not store a FlowToken Vault object at the path " + .concat("/storage/flowTokenVault. ") + .concat("The signer must initialize their account with this vault first!")) + // Withdraw from the signer's FlowToken Vault + self.mintCost = 1.0 + let fundingVault <- sourceVault.withdraw(amount: self.mintCost) as! @FlowToken.Vault + // Deposit the mint cost into the COA + self.coa.deposit(from: <-fundingVault) + + /* Set the WFLOW contract address */ + // + // View the cannonical WFLOW contract at: + // https://evm-testnet.flowscan.io/address/0xd3bF53DAC106A0290B0483EcBC89d40FcC961f3e + self.wflowAddress = EVM.addressFromString(wflowAddressHex) + } + + pre { + self.coa.balance().inFLOW() >= self.mintCost: + "CadenceOwnedAccount holds insufficient FLOW balance to mint - " + .concat("Ensure COA has at least ".concat(self.mintCost.toString()).concat(" FLOW")) + } + + execute { + /* Wrap FLOW in EVM as WFLOW */ + // + // Encode calldata & set value + let depositCalldata = EVM.encodeABIWithSignature("deposit()", []) + let value = EVM.Balance(attoflow: 0) + value.setFLOW(flow: self.mintCost) + // Call the WFLOW contract, wrapping the sent FLOW + let wrapResult = self.coa.call( + to: self.wflowAddress, + data: depositCalldata, + gasLimit: 15_000_000, + value: value + ) + assert( + wrapResult.status == EVM.Status.successful, + message: "Wrapping FLOW as WFLOW failed: ".concat(wrapResult.errorMessage) + ) + } +} diff --git a/cadence/transactions/stepwise/2_approve.cdc b/cadence/transactions/stepwise/2_approve.cdc new file mode 100644 index 0000000..02865dc --- /dev/null +++ b/cadence/transactions/stepwise/2_approve.cdc @@ -0,0 +1,66 @@ +import "FungibleToken" +import "FlowToken" +import "EVM" + +/// This transaction wraps FLOW as WFLOW, approves an ERC721 contract to move the mint amount, and attempts to mint an +/// ERC721 token. The transaction is reverted if any of the EVM interactions fail +/// +transaction(wflowAddressHex: String, maybeMintERC721AddressHex: String) { + + let coa: auth(EVM.Call) &EVM.CadenceOwnedAccount + let mintCost: UFix64 + let wflowAddress: EVM.EVMAddress + let erc721Address: EVM.EVMAddress + + prepare(signer: auth(SaveValue, BorrowValue) &Account) { + /* COA assignment */ + // + let storagePath = /storage/evm + // Assign the COA reference to the transaction's coa field + self.coa = signer.storage.borrow(from: storagePath) + ?? panic("A CadenceOwnedAccount (COA) Resource could not be found at path ".concat(storagePath.toString()) + .concat(" - ensure the COA Resource is created and saved at this path to enable EVM interactions")) + + /* Fund COA with cost of mint */ + // + self.mintCost = 1.0 + /* Set the WFLOW contract address */ + // + // View the cannonical WFLOW contract at: + // https://evm-testnet.flowscan.io/address/0xd3bF53DAC106A0290B0483EcBC89d40FcC961f3e + self.wflowAddress = EVM.addressFromString(wflowAddressHex) + + /* Assign the ERC721 EVM Address */ + // + // Deserialize the provided ERC721 hex string to an EVM address + self.erc721Address = EVM.addressFromString(maybeMintERC721AddressHex) + } + + pre { + self.coa.balance().inFLOW() >= self.mintCost: + "CadenceOwnedAccount holds insufficient FLOW balance to mint - " + .concat("Ensure COA has at least ".concat(self.mintCost.toString()).concat(" FLOW")) + } + + execute { + /* Approve the ERC721 address for the mint amount */ + // + // Encode calldata approve(address,uint) calldata, providing the ERC721 address & mint amount + let approveCalldata = EVM.encodeABIWithSignature( + "approve(address,uint256)", + [self.erc721Address, UInt256(1_000_000_000_000_000_000)] + ) + // Call the WFLOW contract, approving the ERC721 address to move the mint amount + let approveResult = self.coa.call( + to: self.wflowAddress, + data: approveCalldata, + gasLimit: 15_000_000, + value: EVM.Balance(attoflow: 0) + ) + assert( + approveResult.status == EVM.Status.successful, + message: "Approving ERC721 address on WFLOW contract failed: ".concat(approveResult.errorMessage) + ) + } +} + \ No newline at end of file diff --git a/cadence/transactions/stepwise/3_mint.cdc b/cadence/transactions/stepwise/3_mint.cdc new file mode 100644 index 0000000..70bf04d --- /dev/null +++ b/cadence/transactions/stepwise/3_mint.cdc @@ -0,0 +1,46 @@ +import "FungibleToken" +import "FlowToken" +import "EVM" + +/// This transaction attempts to mint the ERC721 token, reverting if the mint fails +/// +transaction(wflowAddressHex: String, maybeMintERC721AddressHex: String) { + + let coa: auth(EVM.Call) &EVM.CadenceOwnedAccount + let erc721Address: EVM.EVMAddress + + prepare(signer: auth(SaveValue, BorrowValue, IssueStorageCapabilityController, PublishCapability, UnpublishCapability) &Account) { + /* COA assigment */ + // + let storagePath = /storage/evm + + // Assign the COA reference to the transaction's coa field + self.coa = signer.storage.borrow(from: storagePath) + ?? panic("A CadenceOwnedAccount (COA) Resource could not be found at path ".concat(storagePath.toString()) + .concat(" - ensure the COA Resource is created and saved at this path to enable EVM interactions")) + + /* Assign the ERC721 EVM Address */ + // + // Deserialize the provided ERC721 hex string to an EVM address + self.erc721Address = EVM.addressFromString(maybeMintERC721AddressHex) + } + + execute { + /* Attempt to mint ERC721 */ + // + // Encode the mint() calldata + let mintCalldata = EVM.encodeABIWithSignature("mint()", []) + // Call the ERC721 contract, attempting to mint + let mintResult = self.coa.call( + to: self.erc721Address, + data: mintCalldata, + gasLimit: 15_000_000, + value: EVM.Balance(attoflow: 0) + ) + // If mint fails, all other actions in this transaction are reverted + assert( + mintResult.status == EVM.Status.successful, + message: "Minting ERC721 token failed: ".concat(mintResult.errorMessage) + ) + } +} From 26f071e6bff00fb7ca6e2a91269b08cb79ce39ef Mon Sep 17 00:00:00 2001 From: Giovanni Sanchez <108043524+sisyphusSmiling@users.noreply.github.com> Date: Mon, 4 Nov 2024 16:29:56 -0700 Subject: [PATCH 12/20] remove unused GitHub cadence tests workflow --- .github/workflows/cadence_test.yml | 30 ------------------------------ 1 file changed, 30 deletions(-) delete mode 100644 .github/workflows/cadence_test.yml diff --git a/.github/workflows/cadence_test.yml b/.github/workflows/cadence_test.yml deleted file mode 100644 index a3b0c18..0000000 --- a/.github/workflows/cadence_test.yml +++ /dev/null @@ -1,30 +0,0 @@ -name: CI - -on: pull_request - -jobs: - tests: - name: Flow CLI Tests - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - name: Set up Go - uses: actions/setup-go@v3 - with: - go-version: "1.20.x" - - uses: actions/cache@v1 - with: - path: ~/go/pkg/mod - key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} - restore-keys: | - ${{ runner.os }}-go- - - name: Install Flow CLI - run: sh -ci "$(curl -fsSL https://raw.githubusercontent.com/onflow/flow-cli/master/install.sh)" - - name: Flow CLI Version - run: flow version - - name: Update PATH - run: echo "/root/.local/bin" >> $GITHUB_PATH - - name: Install dependencies - run: flow deps install - - name: Run tests - run: flow test --cover --covercode="contracts" --coverprofile="coverage.lcov" cadence/tests/*.cdc From 71206e8f3ce8c5b23b4963c6d8243681819d9cd1 Mon Sep 17 00:00:00 2001 From: Giovanni Sanchez <108043524+sisyphusSmiling@users.noreply.github.com> Date: Mon, 4 Nov 2024 17:31:41 -0700 Subject: [PATCH 13/20] remove WETH9 contract --- solidity/src/test/WETH9.sol | 756 ------------------------------------ 1 file changed, 756 deletions(-) delete mode 100644 solidity/src/test/WETH9.sol diff --git a/solidity/src/test/WETH9.sol b/solidity/src/test/WETH9.sol deleted file mode 100644 index a592dc0..0000000 --- a/solidity/src/test/WETH9.sol +++ /dev/null @@ -1,756 +0,0 @@ -// Copyright (C) 2015, 2016, 2017 Dapphub - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -pragma solidity >=0.4.22 <0.6; - -contract WETH9 { - string public name = "Wrapped Flow"; - string public symbol = "WFLOW"; - uint8 public decimals = 18; - - event Approval(address indexed src, address indexed guy, uint wad); - event Transfer(address indexed src, address indexed dst, uint wad); - event Deposit(address indexed dst, uint wad); - event Withdrawal(address indexed src, uint wad); - - mapping (address => uint) public balanceOf; - mapping (address => mapping (address => uint)) public allowance; - - function() external payable { - deposit(); - } - function deposit() public payable { - balanceOf[msg.sender] += msg.value; - emit Deposit(msg.sender, msg.value); - } - function withdraw(uint wad) public { - require(balanceOf[msg.sender] >= wad); - balanceOf[msg.sender] -= wad; - msg.sender.transfer(wad); - emit Withdrawal(msg.sender, wad); - } - - function totalSupply() public view returns (uint) { - return address(this).balance; - } - - function approve(address guy, uint wad) public returns (bool) { - allowance[msg.sender][guy] = wad; - emit Approval(msg.sender, guy, wad); - return true; - } - - function transfer(address dst, uint wad) public returns (bool) { - return transferFrom(msg.sender, dst, wad); - } - - function transferFrom(address src, address dst, uint wad) - public - returns (bool) - { - require(balanceOf[src] >= wad); - - if (src != msg.sender && allowance[src][msg.sender] != uint(-1)) { - require(allowance[src][msg.sender] >= wad); - allowance[src][msg.sender] -= wad; - } - - balanceOf[src] -= wad; - balanceOf[dst] += wad; - - emit Transfer(src, dst, wad); - - return true; - } -} - - -/* - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. - -*/ \ No newline at end of file From 9dba454aa2c35d8a450ba6c5e30deef37d1b1d1c Mon Sep 17 00:00:00 2001 From: Giovanni Sanchez <108043524+sisyphusSmiling@users.noreply.github.com> Date: Mon, 4 Nov 2024 17:58:32 -0700 Subject: [PATCH 14/20] update transaction comments --- cadence/transactions/bundled/wrap_and_mint.cdc | 18 ++++++++++++++++-- cadence/transactions/stepwise/0_create_coa.cdc | 5 ++++- cadence/transactions/stepwise/1_wrap_flow.cdc | 11 ++++++++++- cadence/transactions/stepwise/2_approve.cdc | 10 ++++++++-- cadence/transactions/stepwise/3_mint.cdc | 11 ++++++++++- 5 files changed, 48 insertions(+), 7 deletions(-) diff --git a/cadence/transactions/bundled/wrap_and_mint.cdc b/cadence/transactions/bundled/wrap_and_mint.cdc index 38e07b6..9424816 100644 --- a/cadence/transactions/bundled/wrap_and_mint.cdc +++ b/cadence/transactions/bundled/wrap_and_mint.cdc @@ -2,8 +2,22 @@ import "FungibleToken" import "FlowToken" import "EVM" -/// This transaction wraps FLOW as WFLOW, approves an ERC721 contract to move the mint amount, and attempts to mint an -/// ERC721 token. The transaction is reverted if any of the EVM interactions fail +/// This transaction demonstrates how multiple EVM calls can be batched in a single Cadence transaction via +/// CadenceOwnedAccount (COA), performing the following actions: +/// +/// 1. Configures a COA in the signer's account if needed +/// 2. Funds the signer's COA with enough FLOW to cover the WFLOW cost of minting an ERC721 token +/// 3. Wraps FLOW as WFLOW - EVM call 1 +/// 4. Approves the example MaybeMintERC721 contract which accepts WFLOW to move the mint amount - EVM call 2 +/// 5. Attempts to mint an ERC721 token - EVM call 3 +/// +/// Importantly, the transaction is reverted if any of the EVM interactions fail returning the account to the original +/// state before the transaction was executed across Cadence & EVM. +/// +/// For more context, see https://github.com/onflow/batched-evm-exec-example +/// +/// @param wflowAddressHex: The EVM address hex of the WFLOW contract as a String +/// @param maybeMintERC721AddressHex: The EVM address hex of the ERC721 contract as a String /// transaction(wflowAddressHex: String, maybeMintERC721AddressHex: String) { diff --git a/cadence/transactions/stepwise/0_create_coa.cdc b/cadence/transactions/stepwise/0_create_coa.cdc index 77f8575..daced72 100644 --- a/cadence/transactions/stepwise/0_create_coa.cdc +++ b/cadence/transactions/stepwise/0_create_coa.cdc @@ -2,7 +2,10 @@ import "FungibleToken" import "FlowToken" import "EVM" -/// Creates a CadenceOwnedAccount & funds with the specified amount. If the COA already exists, the transaction reverts. +/// Creates a CadenceOwnedAccount (COA) & funds with the specified amount. +/// If a COA already exists in storage at /storage/evm, the transaction reverts. +/// +/// @param amount: The amount of FLOW to fund the COA with, sourcing funds from the signer's FlowToken Vault /// transaction(amount: UFix64) { diff --git a/cadence/transactions/stepwise/1_wrap_flow.cdc b/cadence/transactions/stepwise/1_wrap_flow.cdc index ab19d56..00a6534 100644 --- a/cadence/transactions/stepwise/1_wrap_flow.cdc +++ b/cadence/transactions/stepwise/1_wrap_flow.cdc @@ -2,7 +2,16 @@ import "FungibleToken" import "FlowToken" import "EVM" -/// This transaction wraps FLOW as WFLOW, funing the signer's CadenceOwnedAccount with the mint cost +/// This transaction wraps FLOW as WFLOW, sourcing the wrapped FLOW from the signer's FlowToken Vault in the amount of +/// 1.0 FLOW to cover the mint cost of 1 MaybeMintERC721 token. If a CadenceOwnedAccount (COA) is not configured in the +/// signer's account, one is configured, allowing the Flow account to interact with Flow's EVM runtime. +/// +/// While not interesting on its own, this transaction demonstrates a single step in the bundled EVM execution example, +/// showcasing how Cadence can be used to atomically orchestrate multiple EVM interactions in a single transaction. +/// +/// For more context, see https://github.com/onflow/batched-evm-exec-example +/// +/// @param wflowAddressHex: The EVM address hex of the WFLOW contract as a String /// transaction(wflowAddressHex: String) { diff --git a/cadence/transactions/stepwise/2_approve.cdc b/cadence/transactions/stepwise/2_approve.cdc index 02865dc..61338f0 100644 --- a/cadence/transactions/stepwise/2_approve.cdc +++ b/cadence/transactions/stepwise/2_approve.cdc @@ -2,8 +2,14 @@ import "FungibleToken" import "FlowToken" import "EVM" -/// This transaction wraps FLOW as WFLOW, approves an ERC721 contract to move the mint amount, and attempts to mint an -/// ERC721 token. The transaction is reverted if any of the EVM interactions fail +/// This transaction approves the provided ERC721 address to move the mint amount on the WFLOW contract. In this example +/// the mint amount is 1.0 WFLOW. While not included in the code below, this transaction is part of a larger example +/// showcasing how Cadence can be used to atomically orchestrate multiple EVM interactions in a single transaction. +/// +/// For more context, see https://github.com/onflow/batched-evm-exec-example +/// +/// @param wflowAddressHex: The EVM address hex of the WFLOW contract as a String +/// @param maybeMintERC721AddressHex: The EVM address hex of the ERC721 contract as a String /// transaction(wflowAddressHex: String, maybeMintERC721AddressHex: String) { diff --git a/cadence/transactions/stepwise/3_mint.cdc b/cadence/transactions/stepwise/3_mint.cdc index 70bf04d..3bd5504 100644 --- a/cadence/transactions/stepwise/3_mint.cdc +++ b/cadence/transactions/stepwise/3_mint.cdc @@ -2,7 +2,16 @@ import "FungibleToken" import "FlowToken" import "EVM" -/// This transaction attempts to mint the ERC721 token, reverting if the mint fails +/// This transaction attempts to mint the ERC721 token, reverting if the mint fails. The intended example is part of a +/// larger example showcasing how Cadence can be used to atomically orchestrate multiple EVM interactions in a single +/// transaction. In this case, the MaybeMintERC721 contract mints an ERC721 token in exchange for WFLOW with a 50% +/// probability of success. If the mint fails, the transaction can be reverted, ensuring the account is returned to the +/// original state before the transaction was executed across Cadence & EVM. +/// +/// For more context, see https://github.com/onflow/batched-evm-exec-example +/// +/// @param wflowAddressHex: The EVM address hex of the WFLOW contract as a String +/// @param maybeMintERC721AddressHex: The EVM address hex of the ERC721 contract as a String /// transaction(wflowAddressHex: String, maybeMintERC721AddressHex: String) { From ee2030825b191a4e25f3ce928ead70eb21664b35 Mon Sep 17 00:00:00 2001 From: Giovanni Sanchez <108043524+sisyphusSmiling@users.noreply.github.com> Date: Mon, 4 Nov 2024 18:12:31 -0700 Subject: [PATCH 15/20] update README with testnet deployments --- README.md | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index fbec104..8752613 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,14 @@ -### Batched Cadence EVM Execution Example +# Batched Cadence EVM Execution Example > This repo contains an example of how to batch EVM execution on Flow using Cadence. -:building_construction: WIP +:building_construction: Currently work in progress. + +## Deployments + +The relevant contracts can be found at the following addresses on Flow Testnet: + +|Contract|Address| +|---|---| +|`MaybeMintERC72`|[`0xdbC43Ba45381e02825b14322cDdd15eC4B3164E6`](https://evm-testnet.flowscan.io/address/0xdbc43ba45381e02825b14322cddd15ec4b3164e6?tab=contract_code)| +|`WFLOW`|[`0xd3bF53DAC106A0290B0483EcBC89d40FcC961f3e`](https://evm-testnet.flowscan.io/token/0xd3bF53DAC106A0290B0483EcBC89d40FcC961f3e?tab=contract_code)| From 0975463f488125c201f39cfd1dd8f5bfa113379f Mon Sep 17 00:00:00 2001 From: Giovanni Sanchez <108043524+sisyphusSmiling@users.noreply.github.com> Date: Thu, 7 Nov 2024 13:37:50 -0700 Subject: [PATCH 16/20] remove onflow/random-coin-toss --- .gitmodules | 3 --- solidity/lib/random-coin-toss | 1 - 2 files changed, 4 deletions(-) delete mode 160000 solidity/lib/random-coin-toss diff --git a/.gitmodules b/.gitmodules index 9af280a..0254bef 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,6 +7,3 @@ [submodule "solidity/lib/forge-std"] path = solidity/lib/forge-std url = https://github.com/foundry-rs/forge-std -[submodule "solidity/lib/random-coin-toss"] - path = solidity/lib/random-coin-toss - url = https://github.com/onflow/random-coin-toss diff --git a/solidity/lib/random-coin-toss b/solidity/lib/random-coin-toss deleted file mode 160000 index e82dee9..0000000 --- a/solidity/lib/random-coin-toss +++ /dev/null @@ -1 +0,0 @@ -Subproject commit e82dee9bab346049532ef0fd3574037f391e6428 From f5fa952df104520bacb3fe2ed1dc4a6ac7e29536 Mon Sep 17 00:00:00 2001 From: Giovanni Sanchez <108043524+sisyphusSmiling@users.noreply.github.com> Date: Thu, 7 Nov 2024 14:00:29 -0700 Subject: [PATCH 17/20] add Cadence tests & helper solidity contract --- cadence/tests/evm_revertible_random_tests.cdc | 64 ++++++++++++ .../tests/scripts/evm_revertible_random.cdc | 16 +++ cadence/tests/test_helpers.cdc | 44 +++++++++ cadence/tests/transactions/create_coa.cdc | 51 ++++++++++ cadence/tests/transactions/deploy.cdc | 56 +++++++++++ cadence/tests/transactions/move_block.cdc | 19 ++++ cadence/tests/wrap_and_mint_tests.cdc | 99 +++++++++++++++++++ .../src/test/TestCadenceRandomConsumer.sol | 29 ++++++ 8 files changed, 378 insertions(+) create mode 100644 cadence/tests/evm_revertible_random_tests.cdc create mode 100644 cadence/tests/scripts/evm_revertible_random.cdc create mode 100644 cadence/tests/test_helpers.cdc create mode 100644 cadence/tests/transactions/create_coa.cdc create mode 100644 cadence/tests/transactions/deploy.cdc create mode 100644 cadence/tests/transactions/move_block.cdc create mode 100644 cadence/tests/wrap_and_mint_tests.cdc create mode 100644 solidity/src/test/TestCadenceRandomConsumer.sol diff --git a/cadence/tests/evm_revertible_random_tests.cdc b/cadence/tests/evm_revertible_random_tests.cdc new file mode 100644 index 0000000..8ae3dac --- /dev/null +++ b/cadence/tests/evm_revertible_random_tests.cdc @@ -0,0 +1,64 @@ +import Test +import BlockchainHelpers +import "test_helpers.cdc" + +import "EVM" + +access(all) let serviceAccount = Test.serviceAccount() + +access(all) var coaAddress: String = "" +access(all) var testAddress: String = "" + +access(all) +fun setup() { + // Create & fund a CadenceOwnedAccount + let coaRes = executeTransaction( + "./transactions/create_coa.cdc", + [100.0], + serviceAccount + ) + Test.expect(coaRes, Test.beSucceeded()) + + // Extract COA address from event + let coaEvts = Test.eventsOfType(Type()) + let coaEvt = coaEvts[0] as! EVM.CadenceOwnedAccountCreated + coaAddress = coaEvt.address + log("COA address: ".concat(coaAddress)) + + // Deploy WFLOW + let testDeployRes = executeTransaction( + "./transactions/deploy.cdc", + [testBytecode, UInt64(15_000_000), 0.0], + serviceAccount + ) + Test.expect(testDeployRes, Test.beSucceeded()) + + // Extract test address from event + var txnExecEvts = Test.eventsOfType(Type()) + let testEvt = txnExecEvts[2] as! EVM.TransactionExecuted + testAddress = testEvt.contractAddress + + log("Test address: ".concat(testAddress)) +} + +access(all) +fun testGetRevertibleRandomSucceeds() { + let a = getEVMRevertibleRandom(coaHost: serviceAccount.address, testAddress: EVM.addressFromString(testAddress)) + moveBlock() + let b = getEVMRevertibleRandom(coaHost: serviceAccount.address, testAddress: EVM.addressFromString(testAddress)) + moveBlock() + let c = getEVMRevertibleRandom(coaHost: serviceAccount.address, testAddress: EVM.addressFromString(testAddress)) + moveBlock() + let d = getEVMRevertibleRandom(coaHost: serviceAccount.address, testAddress: EVM.addressFromString(testAddress)) + moveBlock() + let e = getEVMRevertibleRandom(coaHost: serviceAccount.address, testAddress: EVM.addressFromString(testAddress)) + moveBlock() + let f = getEVMRevertibleRandom(coaHost: serviceAccount.address, testAddress: EVM.addressFromString(testAddress)) + log(String.join([a.toString(), b.toString(), c.toString(), d.toString(), e.toString(), f.toString()], separator: ", ")) + // Test.assert(a != b || a != c || b != c, message: "getEVMRevertibleRandom should return different values") +} + +access(all) +fun getEVMRevertibleRandom(coaHost: Address, testAddress: EVM.EVMAddress): UInt64 { + return 0 +} \ No newline at end of file diff --git a/cadence/tests/scripts/evm_revertible_random.cdc b/cadence/tests/scripts/evm_revertible_random.cdc new file mode 100644 index 0000000..2f0beab --- /dev/null +++ b/cadence/tests/scripts/evm_revertible_random.cdc @@ -0,0 +1,16 @@ +import "EVM" + +access(all) +fun main(coaHost: Address, testAddress: EVM.EVMAddress): UInt64 { + let coa = getAuthAccount(coaHost).storage + .borrow(from: /storage/evm)! + let res = coa.call( + to: testAddress, + data: EVM.encodeABIWithSignature("getRevertibleRandomInRange(uint64,uint64)", [UInt64(0), UInt64(1000)]), + gasLimit: 15_000_000, + value: EVM.Balance(attoflow: 0) + ) + assert(res.status == EVM.Status.successful, message: "getRevertibleRandomInRange failed") + let decoded = EVM.decodeABI(types: [Type()], data: res.data) + return decoded[0] as! UInt64 +} diff --git a/cadence/tests/test_helpers.cdc b/cadence/tests/test_helpers.cdc new file mode 100644 index 0000000..8fe156d --- /dev/null +++ b/cadence/tests/test_helpers.cdc @@ -0,0 +1,44 @@ +import Test + +// Bytecode constants +access(all) let wflowBytecode = "6080604052600436106100ae5763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166306fdde0381146100b8578063095ea7b31461014257806318160ddd1461017a57806323b872dd146101a15780632e1a7d4d146101cb578063313ce567146101e357806370a082311461020e57806395d89b411461022f578063a9059cbb14610244578063d0e30db0146100ae578063dd62ed3e14610268575b6100b661028f565b005b3480156100c457600080fd5b506100cd6102e7565b6040805160208082528351818301528351919283929083019185019080838360005b838110156101075781810151838201526020016100ef565b50505050905090810190601f1680156101345780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561014e57600080fd5b50610166600160a060020a0360043516602435610375565b604080519115158252519081900360200190f35b34801561018657600080fd5b5061018f6103df565b60408051918252519081900360200190f35b3480156101ad57600080fd5b50610166600160a060020a03600435811690602435166044356103ed565b3480156101d757600080fd5b506100b6600435610533565b3480156101ef57600080fd5b506101f86105e3565b6040805160ff9092168252519081900360200190f35b34801561021a57600080fd5b5061018f600160a060020a03600435166105ec565b34801561023b57600080fd5b506100cd6105fe565b34801561025057600080fd5b50610166600160a060020a0360043516602435610658565b34801561027457600080fd5b5061018f600160a060020a036004358116906024351661066c565b600160a060020a033316600081815260036020908152604091829020805434908101909155825190815291517fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9281900390910190a2565b6000805460408051602060026001851615610100026000190190941693909304601f8101849004840282018401909252818152929183018282801561036d5780601f106103425761010080835404028352916020019161036d565b820191906000526020600020905b81548152906001019060200180831161035057829003601f168201915b505050505081565b600160a060020a03338116600081815260046020908152604080832094871680845294825280832086905580518681529051929493927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a350600192915050565b600160a060020a0330163190565b600160a060020a03831660009081526003602052604081205482111561041257600080fd5b33600160a060020a031684600160a060020a03161415801561045c5750600160a060020a038085166000908152600460209081526040808320339094168352929052205460001914155b156104c257600160a060020a038085166000908152600460209081526040808320339094168352929052205482111561049457600080fd5b600160a060020a03808516600090815260046020908152604080832033909416835292905220805483900390555b600160a060020a03808516600081815260036020908152604080832080548890039055938716808352918490208054870190558351868152935191937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929081900390910190a35060019392505050565b600160a060020a03331660009081526003602052604090205481111561055857600080fd5b600160a060020a033316600081815260036020526040808220805485900390555183156108fc0291849190818181858888f193505050501580156105a0573d6000803e3d6000fd5b50604080518281529051600160a060020a033316917f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65919081900360200190a250565b60025460ff1681565b60036020526000908152604090205481565b60018054604080516020600284861615610100026000190190941693909304601f8101849004840282018401909252818152929183018282801561036d5780601f106103425761010080835404028352916020019161036d565b60006106653384846103ed565b9392505050565b6004602090815260009283526040808420909152908252902054815600a165627a7a72305820e1e0e82b179f331bf99f3294d4266cb1da578c59c07c2de6693f8cb10226617a0029" +access(all) let erc721Bytecode = "60806040523480156200001157600080fd5b506040516200181b3803806200181b833981016040819052620000349162000208565b338585600062000045838262000332565b50600162000054828262000332565b5050506001600160a01b0381166200008657604051631e4fbdf760e01b81526000600482015260240160405180910390fd5b6200009181620000d1565b50600780546001600160a01b039485166001600160a01b0319918216179091556008929092556009805491909316911617905550506000600a55620003fe565b600680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200014b57600080fd5b81516001600160401b038082111562000168576200016862000123565b604051601f8301601f19908116603f0116810190828211818310171562000193576200019362000123565b8160405283815260209250866020858801011115620001b157600080fd5b600091505b83821015620001d55785820183015181830184015290820190620001b6565b6000602085830101528094505050505092915050565b80516001600160a01b03811681146200020357600080fd5b919050565b600080600080600060a086880312156200022157600080fd5b85516001600160401b03808211156200023957600080fd5b6200024789838a0162000139565b965060208801519150808211156200025e57600080fd5b506200026d8882890162000139565b9450506200027e60408701620001eb565b9250606086015191506200029560808701620001eb565b90509295509295909350565b600181811c90821680620002b657607f821691505b602082108103620002d757634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200032d576000816000526020600020601f850160051c81016020861015620003085750805b601f850160051c820191505b81811015620003295782815560010162000314565b5050505b505050565b81516001600160401b038111156200034e576200034e62000123565b62000366816200035f8454620002a1565b84620002dd565b602080601f8311600181146200039e5760008415620003855750858301515b600019600386901b1c1916600185901b17855562000329565b600085815260208120601f198616915b82811015620003cf57888601518255948401946001909101908401620003ae565b5085821015620003ee5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b61140d806200040e6000396000f3fe608060405234801561001057600080fd5b50600436106101375760003560e01c806370a08231116100b8578063a22cb4651161007c578063a22cb4651461026b578063b88d4fde1461027e578063bdb4b84814610291578063c87b56dd1461029a578063e985e9c5146102ad578063f2fde38b146102c057600080fd5b806370a0823114610224578063715018a6146102375780638bca6d161461023f5780638da5cb5b1461025257806395d89b411461026357600080fd5b806318160ddd116100ff57806318160ddd146101c157806323b872dd146101d857806338af3eed146101eb57806342842e0e146101fe5780636352211e1461021157600080fd5b806301ffc9a71461013c57806306fdde0314610164578063081812fc14610179578063095ea7b3146101a45780631249c58b146101b9575b600080fd5b61014f61014a366004610fb5565b6102d3565b60405190151581526020015b60405180910390f35b61016c610325565b60405161015b9190611022565b61018c610187366004611035565b6103b7565b6040516001600160a01b03909116815260200161015b565b6101b76101b236600461106a565b6103e0565b005b6101b76103ef565b6101ca600a5481565b60405190815260200161015b565b6101b76101e6366004611094565b6103f9565b60095461018c906001600160a01b031681565b6101b761020c366004611094565b610489565b61018c61021f366004611035565b6104a9565b6101ca6102323660046110d0565b6104b4565b6101b76104fc565b60075461018c906001600160a01b031681565b6006546001600160a01b031661018c565b61016c61050e565b6101b76102793660046110f9565b61051d565b6101b761028c366004611146565b610528565b6101ca60085481565b61016c6102a8366004611035565b610540565b61014f6102bb366004611222565b6105b5565b6101b76102ce3660046110d0565b6105e3565b60006001600160e01b031982166380ac58cd60e01b148061030457506001600160e01b03198216635b5e139f60e01b145b8061031f57506301ffc9a760e01b6001600160e01b03198316145b92915050565b60606000805461033490611255565b80601f016020809104026020016040519081016040528092919081815260200182805461036090611255565b80156103ad5780601f10610382576101008083540402835291602001916103ad565b820191906000526020600020905b81548152906001019060200180831161039057829003601f168201915b5050505050905090565b60006103c282610621565b506000828152600460205260409020546001600160a01b031661031f565b6103eb82823361065a565b5050565b6103f7610667565b565b6001600160a01b03821661042857604051633250574960e11b8152600060048201526024015b60405180910390fd5b6000610435838333610746565b9050836001600160a01b0316816001600160a01b031614610483576040516364283d7b60e01b81526001600160a01b038086166004830152602482018490528216604482015260640161041f565b50505050565b6104a483838360405180602001604052806000815250610528565b505050565b600061031f82610621565b60006001600160a01b0382166104e0576040516322718ad960e21b81526000600482015260240161041f565b506001600160a01b031660009081526003602052604090205490565b61050461083f565b6103f7600061086c565b60606001805461033490611255565b6103eb3383836108be565b6105338484846103f9565b610483338585858561095d565b606061054b82610621565b50600061056360408051602081019091526000815290565b9050600081511161058357604051806020016040528060008152506105ae565b8061058d84610a88565b60405160200161059e92919061128f565b6040516020818303038152906040525b9392505050565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b6105eb61083f565b6001600160a01b03811661061557604051631e4fbdf760e01b81526000600482015260240161041f565b61061e8161086c565b50565b6000818152600260205260408120546001600160a01b03168061031f57604051637e27328960e01b81526004810184905260240161041f565b6104a48383836001610b1b565b61066f610c21565b6007546009546008546040516323b872dd60e01b81523360048201526001600160a01b03928316602482015260448101919091529116906323b872dd906064016020604051808303816000875af19250505080156106ea575060408051601f3d908101601f191682019092526106e7918101906112be565b60015b6107245760075460085460405163760a9bc360e11b81526001600160a01b039092166004830152336024830152604482015260640161041f565b50600a8054906000610735836112db565b91905055506103f733600a54610c62565b6000828152600260205260408120546001600160a01b039081169083161561077357610773818486610cc7565b6001600160a01b038116156107b157610790600085600080610b1b565b6001600160a01b038116600090815260036020526040902080546000190190555b6001600160a01b038516156107e0576001600160a01b0385166000908152600360205260409020805460010190555b60008481526002602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4949350505050565b6006546001600160a01b031633146103f75760405163118cdaa760e01b815233600482015260240161041f565b600680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6001600160a01b0382166108f057604051630b61174360e31b81526001600160a01b038316600482015260240161041f565b6001600160a01b03838116600081815260056020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6001600160a01b0383163b15610a8157604051630a85bd0160e11b81526001600160a01b0384169063150b7a029061099f908890889087908790600401611302565b6020604051808303816000875af19250505080156109da575060408051601f3d908101601f191682019092526109d79181019061133f565b60015b610a43573d808015610a08576040519150601f19603f3d011682016040523d82523d6000602084013e610a0d565b606091505b508051600003610a3b57604051633250574960e11b81526001600160a01b038516600482015260240161041f565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b14610a7f57604051633250574960e11b81526001600160a01b038516600482015260240161041f565b505b5050505050565b60606000610a9583610d2b565b600101905060008167ffffffffffffffff811115610ab557610ab5611130565b6040519080825280601f01601f191660200182016040528015610adf576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a8504945084610ae957509392505050565b8080610b2f57506001600160a01b03821615155b15610bf1576000610b3f84610621565b90506001600160a01b03831615801590610b6b5750826001600160a01b0316816001600160a01b031614155b8015610b7e5750610b7c81846105b5565b155b15610ba75760405163a9fbf51f60e01b81526001600160a01b038416600482015260240161041f565b8115610bef5783856001600160a01b0316826001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45b505b5050600090815260046020526040902080546001600160a01b0319166001600160a01b0392909216919091179055565b6000610c2b610e03565b9050610c3860028261135c565b67ffffffffffffffff1660010361061e576040516351d099d960e11b815260040160405180910390fd5b6001600160a01b038216610c8c57604051633250574960e11b81526000600482015260240161041f565b6000610c9a83836000610746565b90506001600160a01b038116156104a4576040516339e3563760e11b81526000600482015260240161041f565b610cd2838383610f3c565b6104a4576001600160a01b038316610d0057604051637e27328960e01b81526004810182905260240161041f565b60405163177e802f60e01b81526001600160a01b03831660048201526024810182905260440161041f565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b8310610d6a5772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef81000000008310610d96576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc100008310610db457662386f26fc10000830492506010015b6305f5e1008310610dcc576305f5e100830492506008015b6127108310610de057612710830492506004015b60648310610df2576064830492506002015b600a831061031f5760010192915050565b60408051600481526024810182526020810180516001600160e01b0316630382fd5960e51b1790529051600091829182916801000000000000000191610e499190611391565b600060405180830381855afa9150503d8060008114610e84576040519150601f19603f3d011682016040523d82523d6000602084013e610e89565b606091505b509150915081610f1e5760405162461bcd60e51b815260206004820152605460248201527f556e7375636365737366756c2063616c6c20746f20436164656e63652041726360448201527f68207072652d636f6d70696c65207768656e206665746368696e672072657665606482015273393a34b13632903930b73237b690373ab6b132b960611b608482015260a40161041f565b600081806020019051810190610f3491906113ad565b949350505050565b60006001600160a01b03831615801590610f345750826001600160a01b0316846001600160a01b03161480610f765750610f7684846105b5565b80610f345750506000908152600460205260409020546001600160a01b03908116911614919050565b6001600160e01b03198116811461061e57600080fd5b600060208284031215610fc757600080fd5b81356105ae81610f9f565b60005b83811015610fed578181015183820152602001610fd5565b50506000910152565b6000815180845261100e816020860160208601610fd2565b601f01601f19169290920160200192915050565b6020815260006105ae6020830184610ff6565b60006020828403121561104757600080fd5b5035919050565b80356001600160a01b038116811461106557600080fd5b919050565b6000806040838503121561107d57600080fd5b6110868361104e565b946020939093013593505050565b6000806000606084860312156110a957600080fd5b6110b28461104e565b92506110c06020850161104e565b9150604084013590509250925092565b6000602082840312156110e257600080fd5b6105ae8261104e565b801515811461061e57600080fd5b6000806040838503121561110c57600080fd5b6111158361104e565b91506020830135611125816110eb565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b6000806000806080858703121561115c57600080fd5b6111658561104e565b93506111736020860161104e565b925060408501359150606085013567ffffffffffffffff8082111561119757600080fd5b818701915087601f8301126111ab57600080fd5b8135818111156111bd576111bd611130565b604051601f8201601f19908116603f011681019083821181831017156111e5576111e5611130565b816040528281528a60208487010111156111fe57600080fd5b82602086016020830137600060208483010152809550505050505092959194509250565b6000806040838503121561123557600080fd5b61123e8361104e565b915061124c6020840161104e565b90509250929050565b600181811c9082168061126957607f821691505b60208210810361128957634e487b7160e01b600052602260045260246000fd5b50919050565b600083516112a1818460208801610fd2565b8351908301906112b5818360208801610fd2565b01949350505050565b6000602082840312156112d057600080fd5b81516105ae816110eb565b6000600182016112fb57634e487b7160e01b600052601160045260246000fd5b5060010190565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061133590830184610ff6565b9695505050505050565b60006020828403121561135157600080fd5b81516105ae81610f9f565b600067ffffffffffffffff8084168061138557634e487b7160e01b600052601260045260246000fd5b92169190910692915050565b600082516113a3818460208701610fd2565b9190910192915050565b6000602082840312156113bf57600080fd5b815167ffffffffffffffff811681146105ae57600080fdfea26469706673582212204919ee1872648a1b85d633af14a8f8c7163d176b6699f75fe4e22d677fc562ae64736f6c63430008180033" +access(all) let testBytecode = "608060405234801561001057600080fd5b50611210806100206000396000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c80635461f2e41461005c578063bc26d8241461008c578063d59fd63c1461009f578063f8413b07146100c2578063fc177f7f146100d8575b600080fd5b61006f61006a366004610fac565b6100eb565b6040516001600160401b0390911681526020015b60405180910390f35b61006f61009a366004610fe5565b610100565b6100b26100ad366004610fe5565b61010b565b6040519015158152602001610083565b6100ca610189565b604051908152602001610083565b61006f6100e6366004610ffe565b610198565b60006100f783836101ad565b90505b92915050565b60006100fa82610225565b600080610119600184611056565b600054909150811061012e5750600092915050565b600080828154811061014257610142611069565b90600052602060002090600302019050600061015c6102df565b600283015490915060ff16158015610180575081546001600160401b038083169116105b95945050505050565b600061019361040e565b905090565b60006101a584848461054f565b949350505050565b6000806101b861060d565b6040516020016101ca91815260200190565b60408051601f1981840301815282825243602084015292506000910160408051601f1981840301815282820190915260008083526020830152915061021081848461066a565b61021b81878761079d565b9695505050505050565b600080610231836108cc565b60405160200161024391815260200190565b60408051601f198184030181528282526020830186905292506000910160408051601f1981840301815282820190915260008083526020830152915061028a81848461066a565b600061029582610a11565b6040516001600160401b038216815290915086907fe3e452ff947e18cea0f62f23d405e522ac808f69346c5f59ddc4bd722ac10d039060200160405180910390a295945050505050565b60408051600481526024810182526020810180516001600160e01b03166329f43eb360e11b179052905160009182918291680100000000000000019161032591906110af565b600060405180830381855afa9150503d8060008114610360576040519150601f19603f3d011682016040523d82523d6000602084013e610365565b606091505b5091509150816103f85760405162461bcd60e51b815260206004820152604d60248201527f556e7375636365737366756c2063616c6c20746f20436164656e63652041726360448201527f68207072652d636f6d70696c65207768656e206665746368696e6720466c6f7760648201526c08189b1bd8dac81a195a59da1d609a1b608482015260a4015b60405180910390fd5b6000818060200190518101906101a591906110bb565b600180546000918261041f836110df565b919050555060006001549050600060405180606001604052806104406102df565b6001600160401b0390811682524360208084019190915260006040938401819052805460018101825590805284517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5636003909202918201805467ffffffffffffffff191691909416908117909355848201517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5648201819055858501517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e565909201805460ff19169215159290921790915583519283529082015291925083917f7886956edccde10901843c3e51fc26016455e9248e210a29c2a57ead63ad226e910160405180910390a250919050565b60008061055b856108cc565b60405160200161056d91815260200190565b60408051601f198184030181528282526020830188905292506000910160408051601f198184030181528282019091526000808352602083015291506105b481848461066a565b60006105c182888861079d565b6040516001600160401b038216815290915088907fe3e452ff947e18cea0f62f23d405e522ac808f69346c5f59ddc4bd722ac10d039060200160405180910390a2979650505050505050565b600080610618610a6e565b6001600160401b03169050604061062d610a6e565b6001600160401b0316901b176080610643610a6e565b6001600160401b0316901b1760c0610659610a6e565b6001600160401b0316901b17919050565b6010825110156106f05760405162461bcd60e51b815260206004820152604560248201527f4174206c65617374203136206279746573206f6620656e74726f70792073686f60448201527f756c642062652075736564207768656e20696e697469616c697a696e67207468606482015264652050524760d81b608482015260a4016103ef565b600082826040516020016107059291906110f8565b604051602081830303815290604052905060008180519060200120905061074e8160405160200161073891815260200190565b6040516020818303038152906040526000610b89565b6001600160401b03168552604080516020810183905261077f91016040516020818303038152906040526008610b89565b6001600160401b0316602086015261079685610c41565b5050505050565b6000826001600160401b0316826001600160401b0316116108005760405162461bcd60e51b815260206004820152601c60248201527f4d6178206d7573742062652067726561746572207468616e206d696e0000000060448201526064016103ef565b600061080c848461110d565b9050600061081982610cda565b9050600061083460016001600160401b03841681901b611056565b9050600061084483610100611134565b6001600160401b03169050600080600061085d8b610d10565b90505b8481169150866001600160401b0316826001600160401b031611156108b3576001600160401b0386161c82610894816110df565b9350508383036108ae576108a78b610d10565b9050600092505b610860565b6108bd828b611168565b9b9a5050505050505050505050565b6000806108da600184611056565b600054909150811061095f5760405162461bcd60e51b815260206004820152604260248201527f496e76616c69642072657175657374204944202d2076616c756520657863656560448201527f647320746865206e756d626572206f66206578697374696e6720726571756573606482015261747360f01b608482015260a4016103ef565b600080828154811061097357610973611069565b9060005260206000209060030201905061098c81610d72565b60028101805460ff1916600117905580546000906109b2906001600160401b0316610e5b565b82546001840154604080516001600160401b0390931683526020830191909152810182905290915085907f01f207584638dfbb3f1d85bba3809672fcb07a3d2e291308293ba78b7f1984909060600160405180910390a2949350505050565b6000610a1c82610c41565b5080516020820180516001600160401b03808216909452601783901b6a7fffffffffffffff80000016909218601181901c657fffffffffff1618601a83901c643fffffffff1683181892831690520190565b60408051600481526024810182526020810180516001600160e01b0316630382fd5960e51b1790529051600091829182916801000000000000000191610ab491906110af565b600060405180830381855afa9150503d8060008114610aef576040519150601f19603f3d011682016040523d82523d6000602084013e610af4565b606091505b5091509150816103f85760405162461bcd60e51b815260206004820152605460248201527f556e7375636365737366756c2063616c6c20746f20436164656e63652041726360448201527f68207072652d636f6d70696c65207768656e206665746368696e672072657665606482015273393a34b13632903930b73237b690373ab6b132b960611b608482015260a4016103ef565b6000610b96826008611188565b83511015610bdc5760405162461bcd60e51b8152602060048201526013602482015272092dcecc2d8d2c840c4f2e8ca40d8cadccee8d606b1b60448201526064016103ef565b6000805b6008811015610c395784610bf48286611188565b81518110610c0457610c04611069565b602001015160f81c60f81b60f81c60ff166008836001600160401b0316901b1791508080610c31906110df565b915050610be0565b509392505050565b80516001600160401b0316151580610c65575060208101516001600160401b031615155b610cd75760405162461bcd60e51b815260206004820152603860248201527f50524720696e697469616c2073746174652069732030202d206d75737420626560448201527f20696e697469616c697a6564206173206e6f6e2d7a65726f000000000000000060648201526084016103ef565b50565b6000805b6001600160401b038316156100fa576001836001600160401b0316901c92508080610d089061119b565b915050610cde565b600080610d1c83610a11565b6001600160401b031690506040610d3284610a11565b6001600160401b0316901b176080610d4984610a11565b6001600160401b0316901b1760c0610d6084610a11565b6001600160401b0316901b1792915050565b600281015460ff1615610dc75760405162461bcd60e51b815260206004820152601960248201527f5265717565737420616c72656164792066756c66696c6c65640000000000000060448201526064016103ef565b610dcf6102df565b81546001600160401b03918216911610610cd75760405162461bcd60e51b815260206004820152604160248201527f43616e6e6f742066756c66696c6c207265717565737420756e74696c2073756260448201527f73657175656e7420466c6f77206e6574776f726b20626c6f636b2068656967686064820152601d60fa1b608482015260a4016103ef565b6040516001600160401b038216602482015260009081908190680100000000000000019060440160408051601f198184030181529181526020820180516001600160e01b0316633c53afdf60e11b17905251610eb791906110af565b600060405180830381855afa9150503d8060008114610ef2576040519150601f19603f3d011682016040523d82523d6000602084013e610ef7565b606091505b509150915081610f815760405162461bcd60e51b815260206004820152604960248201527f556e7375636365737366756c2063616c6c20746f20436164656e63652041726360448201527f68207072652d636f6d70696c65207768656e206665746368696e672072616e646064820152686f6d20736f7572636560b81b608482015260a4016103ef565b60008180602001905181019061018091906111c1565b6001600160401b0381168114610cd757600080fd5b60008060408385031215610fbf57600080fd5b8235610fca81610f97565b91506020830135610fda81610f97565b809150509250929050565b600060208284031215610ff757600080fd5b5035919050565b60008060006060848603121561101357600080fd5b83359250602084013561102581610f97565b9150604084013561103581610f97565b809150509250925092565b634e487b7160e01b600052601160045260246000fd5b818103818111156100fa576100fa611040565b634e487b7160e01b600052603260045260246000fd5b6000815160005b818110156110a05760208185018101518683015201611086565b50600093019283525090919050565b60006100f7828461107f565b6000602082840312156110cd57600080fd5b81516110d881610f97565b9392505050565b6000600182016110f1576110f1611040565b5060010190565b60006101a5611107838661107f565b8461107f565b6001600160401b0382811682821603908082111561112d5761112d611040565b5092915050565b60006001600160401b038084168061115c57634e487b7160e01b600052601260045260246000fd5b92169190910492915050565b6001600160401b0381811683821601908082111561112d5761112d611040565b808201808211156100fa576100fa611040565b60006001600160401b038083168181036111b7576111b7611040565b6001019392505050565b6000602082840312156111d357600080fd5b505191905056fea2646970667358221220f8c9a068ce5c9c1b3f61e3676f66b60a38347f8e7f4830594074a9377b82688564736f6c63430008130033" + +/* --- Getters --- */ + +access(all) +fun getWFLOWBytecode(): String { + return wflowBytecode +} + +access(all) +fun getERC721Bytecode(): String { + return erc721Bytecode +} + +access(all) +fun getTestBytecode(): String { + return testBytecode +} + +access(all) +fun moveBlock() { + let res = _executeTransaction( + "./transactions/move_block.cdc", + [], + Test.serviceAccount() + ) + Test.expect(res, Test.beSucceeded()) +} + +access(all) +fun _executeTransaction(_ path: String, _ args: [AnyStruct], _ signer: Test.TestAccount): Test.TransactionResult { + let txn = Test.Transaction( + code: Test.readFile(path), + authorizers: [signer.address], + signers: [signer], + arguments: args + ) + return Test.executeTransaction(txn) +} \ No newline at end of file diff --git a/cadence/tests/transactions/create_coa.cdc b/cadence/tests/transactions/create_coa.cdc new file mode 100644 index 0000000..d60ca38 --- /dev/null +++ b/cadence/tests/transactions/create_coa.cdc @@ -0,0 +1,51 @@ +import "EVM" +import "FungibleToken" +import "FlowToken" + +/// Configures a COA in the signer's Flow account, funding with the specified amount. If the COA already exists, the +/// transaction reverts. +/// +transaction(amount: UFix64) { + let coa: &EVM.CadenceOwnedAccount + let sentVault: @FlowToken.Vault + + prepare(signer: auth(BorrowValue, IssueStorageCapabilityController, PublishCapability, SaveValue, UnpublishCapability) &Account) { + let storagePath = /storage/evm + let publicPath = /public/evm + + // Revert if the CadenceOwnedAccount already exists + if signer.storage.type(at: storagePath) != nil { + panic("Storage collision - Resource already stored at path=".concat(storagePath.toString())) + } + + // Configure the CadenceOwnedAccount + signer.storage.save<@EVM.CadenceOwnedAccount>(<-EVM.createCadenceOwnedAccount(), to: storagePath) + let addressableCap = signer.capabilities.storage.issue<&EVM.CadenceOwnedAccount>(storagePath) + signer.capabilities.unpublish(publicPath) + signer.capabilities.publish(addressableCap, at: publicPath) + + // Reference the CadeceOwnedAccount + self.coa = signer.storage.borrow(from: /storage/evm) + ?? panic("Missing or mis-typed CadenceOwnedAccount at /storage/evm") + + // Withdraw the amount from the signer's FlowToken vault + let vaultRef = signer.storage.borrow( + from: /storage/flowTokenVault + ) ?? panic("Could not borrow reference to the owner's Vault!") + self.sentVault <- vaultRef.withdraw(amount: amount) as! @FlowToken.Vault + } + + pre { + self.sentVault.balance == amount: + "Expected amount =".concat(amount.toString()).concat(" but sentVault.balance=").concat(self.sentVault.balance.toString()) + } + + execute { + // Deposit the amount into the CadenceOwnedAccount if the balance is greater than zero + if self.sentVault.balance > 0.0 { + self.coa.deposit(from: <-self.sentVault) + } else { + destroy self.sentVault + } + } +} \ No newline at end of file diff --git a/cadence/tests/transactions/deploy.cdc b/cadence/tests/transactions/deploy.cdc new file mode 100644 index 0000000..221fef8 --- /dev/null +++ b/cadence/tests/transactions/deploy.cdc @@ -0,0 +1,56 @@ +import "FungibleToken" +import "FlowToken" + +import "EVM" + +/// Deploys a compiled solidity contract from bytecode to the EVM, with the signer's COA as the deployer +/// +transaction(bytecode: String, gasLimit: UInt64, value: UFix64) { + + let coa: auth(EVM.Deploy) &EVM.CadenceOwnedAccount + var sentVault: @FlowToken.Vault? + + prepare(signer: auth(BorrowValue) &Account) { + + let storagePath = StoragePath(identifier: "evm")! + self.coa = signer.storage.borrow(from: storagePath) + ?? panic("Could not borrow reference to the signer's bridged account") + + // Rebalance Flow across VMs if there is not enough Flow in the EVM account to cover the value + let evmFlowBalance: UFix64 = self.coa.balance().inFLOW() + if self.coa.balance().inFLOW() < value { + let withdrawAmount: UFix64 = value - evmFlowBalance + let vaultRef = signer.storage.borrow( + from: /storage/flowTokenVault + ) ?? panic("Could not borrow reference to the owner's Vault!") + + self.sentVault <- vaultRef.withdraw(amount: withdrawAmount) as! @FlowToken.Vault + } else { + self.sentVault <- nil + } + } + + execute { + + // Deposit Flow into the EVM account if necessary otherwise destroy the sent Vault + if self.sentVault != nil { + self.coa.deposit(from: <-self.sentVault!) + } else { + destroy self.sentVault + } + + let valueBalance = EVM.Balance(attoflow: 0) + valueBalance.setFLOW(flow: value) + // Finally deploy the contract + let evmResult = self.coa.deploy( + code: bytecode.decodeHex(), + gasLimit: gasLimit, + value: valueBalance + ) + assert( + evmResult.status == EVM.Status.successful && evmResult.deployedContract != nil, + message: "EVM deployment failed with error code: ".concat(evmResult.errorCode.toString()) + .concat(" and message: ").concat(evmResult.errorMessage) + ) + } +} diff --git a/cadence/tests/transactions/move_block.cdc b/cadence/tests/transactions/move_block.cdc new file mode 100644 index 0000000..aa50595 --- /dev/null +++ b/cadence/tests/transactions/move_block.cdc @@ -0,0 +1,19 @@ +import "EVM" + +transaction { + let coa: auth(EVM.Call) &EVM.CadenceOwnedAccount + prepare(signer: auth(BorrowValue) &Account) { + self.coa = signer.storage.borrow(from: /storage/evm) + ?? panic("A CadenceOwnedAccount (COA) Resource could not be found at path /storage/evm") + } + + execute { + let res = self.coa.call( + to: self.coa.address(), + data: [], + gasLimit: 15_000_000, + value: EVM.Balance(attoflow: 0) + ) + assert(res.status == EVM.Status.successful, message: "Empty EVM call failed") + } +} diff --git a/cadence/tests/wrap_and_mint_tests.cdc b/cadence/tests/wrap_and_mint_tests.cdc new file mode 100644 index 0000000..fde9ff2 --- /dev/null +++ b/cadence/tests/wrap_and_mint_tests.cdc @@ -0,0 +1,99 @@ +import Test +import BlockchainHelpers +import "test_helpers.cdc" + +import "EVM" + +access(all) let serviceAccount = Test.serviceAccount() + +access(all) var coaAddress: String = "" +access(all) var wflowAddress: String = "" +access(all) var erc721Address: String = "" + +access(all) +fun setup() { + // Create & fund a CadenceOwnedAccount + let coaRes = executeTransaction( + "./transactions/create_coa.cdc", + [100.0], + serviceAccount + ) + Test.expect(coaRes, Test.beSucceeded()) + + // Extract COA address from event + let coaEvts = Test.eventsOfType(Type()) + let coaEvt = coaEvts[0] as! EVM.CadenceOwnedAccountCreated + coaAddress = coaEvt.address + log("COA address: ".concat(coaAddress)) + + // Deploy WFLOW + let wflowDeployRes = executeTransaction( + "./transactions/deploy.cdc", + [getWFLOWBytecode(), UInt64(15_000_000), 0.0], + serviceAccount + ) + Test.expect(wflowDeployRes, Test.beSucceeded()) + + // Extract WFLOW address from event + var txnExecEvts = Test.eventsOfType(Type()) + let wflowEvt = txnExecEvts[2] as! EVM.TransactionExecuted + wflowAddress = wflowEvt.contractAddress + + // Deploy ERC721 + let constructorArgs = [ + "Maybe Mint ERC721", + "MAYBE", + EVM.addressFromString(wflowAddress), + UInt256(1_000_000_000_000_000_000), + EVM.addressFromString(coaAddress) + ] + // Encode constructor args as ABI and then as hex + let argsBytecode = String.encodeHex(EVM.encodeABI( + constructorArgs + )) + // Append the encoded constructor args to the compiled bytecode + let finalBytecode = getERC721Bytecode().concat(argsBytecode) + let erc721DeployRes = executeTransaction( + "./transactions/deploy.cdc", + [finalBytecode, UInt64(15_000_000), 0.0], + serviceAccount + ) + Test.expect(erc721DeployRes, Test.beSucceeded()) + + // Extract ERC721 address from event + txnExecEvts = Test.eventsOfType(Type()) + let erc721Evt = txnExecEvts[3] as! EVM.TransactionExecuted + erc721Address = erc721Evt.contractAddress + + log("WFLOW address: ".concat(wflowAddress)) + log("ERC721 address: ".concat(erc721Address)) +} + +access(all) +fun testWrapAndMintSucceeds() { + let user = Test.createAccount() + mintFlow(to: user, amount: 10.0) + + wrapAndMintUntilSuccess(signer: user, wflow: wflowAddress, erc721: erc721Address) +} + +access(all) +fun wrapAndMintUntilSuccess(signer: Test.TestAccount, wflow: String, erc721: String) { + var i = 0 + var success = false + while i < 50 { + let res: Test.TransactionResult = executeTransaction( + "../transactions/bundled/wrap_and_mint.cdc", + [wflow, erc721], + signer + ) + if res.error == nil { + success = true + break + } else { + i = i + 1 + moveBlock() + } + } + Test.assertEqual(true, success) +} \ No newline at end of file diff --git a/solidity/src/test/TestCadenceRandomConsumer.sol b/solidity/src/test/TestCadenceRandomConsumer.sol new file mode 100644 index 0000000..950b6f2 --- /dev/null +++ b/solidity/src/test/TestCadenceRandomConsumer.sol @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: Unlicense +pragma solidity 0.8.19; + +import {CadenceRandomConsumer} from "onflow/random-coin-toss/solidity/src/CadenceRandomConsumer.sol"; + +/** + * @dev This contract extends CadenceRandomConsumer to expose internal functions for testing. + */ +contract TestCadenceRandomConsumer is CadenceRandomConsumer { + // Expose internal _getRevertibleRandomInRange function for testing + function getRevertibleRandomInRange(uint64 min, uint64 max) public view returns (uint64) { + return _getRevertibleRandomInRange(min, max); + } + + // Expose internal _requestRandomness function for testing + function requestRandomness() public returns (uint256) { + return _requestRandomness(); + } + + // Expose internal _fulfillRandomRequest function for testing + function fulfillRandomRequest(uint256 requestId) public returns (uint64) { + return _fulfillRandomRequest(requestId); + } + + // Expose internal _fulfillRandomInRange function for testing + function fulfillRandomInRange(uint256 requestId, uint64 min, uint64 max) public returns (uint64) { + return _fulfillRandomInRange(requestId, min, max); + } +} From bffd6322e89c83ee8db4163cbced09cf23adb12b Mon Sep 17 00:00:00 2001 From: Giovanni Sanchez <108043524+sisyphusSmiling@users.noreply.github.com> Date: Thu, 7 Nov 2024 14:02:46 -0700 Subject: [PATCH 18/20] forge install: flow-sol-utils --- .gitmodules | 3 +++ solidity/lib/flow-sol-utils | 1 + 2 files changed, 4 insertions(+) create mode 160000 solidity/lib/flow-sol-utils diff --git a/.gitmodules b/.gitmodules index 0254bef..35f6bab 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,3 +7,6 @@ [submodule "solidity/lib/forge-std"] path = solidity/lib/forge-std url = https://github.com/foundry-rs/forge-std +[submodule "solidity/lib/flow-sol-utils"] + path = solidity/lib/flow-sol-utils + url = https://github.com/onflow/flow-sol-utils diff --git a/solidity/lib/flow-sol-utils b/solidity/lib/flow-sol-utils new file mode 160000 index 0000000..082dd3e --- /dev/null +++ b/solidity/lib/flow-sol-utils @@ -0,0 +1 @@ +Subproject commit 082dd3ec59eea0e8afacb3b49903a7564ce9ce66 From c4b6971f57defb480cc51ba1915e0a0df10f3340 Mon Sep 17 00:00:00 2001 From: Giovanni Sanchez <108043524+sisyphusSmiling@users.noreply.github.com> Date: Thu, 7 Nov 2024 14:11:17 -0700 Subject: [PATCH 19/20] update solidity dependencies to use flow-sol-utils --- remappings.txt | 2 +- solidity/src/MaybeMintERC721.sol | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/remappings.txt b/remappings.txt index 5776ef6..037966e 100644 --- a/remappings.txt +++ b/remappings.txt @@ -3,4 +3,4 @@ ds-test/=solidity/lib/forge-std/lib/ds-test/src/ erc4626-tests/=solidity/lib/openzeppelin-contracts/lib/erc4626-tests/ forge-std/=solidity/lib/forge-std/src/ openzeppelin-contracts/=solidity/lib/openzeppelin-contracts/ -onflow/random-coin-toss=solidity/lib/random-coin-toss \ No newline at end of file +flow-sol-utils=solidity/lib/flow-sol-utils/src/ \ No newline at end of file diff --git a/solidity/src/MaybeMintERC721.sol b/solidity/src/MaybeMintERC721.sol index 47c0620..3f44a87 100644 --- a/solidity/src/MaybeMintERC721.sol +++ b/solidity/src/MaybeMintERC721.sol @@ -3,7 +3,7 @@ pragma solidity 0.8.24; import {ERC721} from "@openzeppelin/contracts/token/ERC721/ERC721.sol"; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; -import {CadenceArchUtils} from "onflow/random-coin-toss/solidity/src/CadenceArchUtils.sol"; +import {CadenceArchUtils} from "flow-sol-utils/cadence-arch/CadenceArchUtils.sol"; /** * @title MaybeMintERC721 From d203cc90bf760a36eeb35cd807d6a12f643196cb Mon Sep 17 00:00:00 2001 From: Giovanni Sanchez <108043524+sisyphusSmiling@users.noreply.github.com> Date: Thu, 7 Nov 2024 14:59:47 -0700 Subject: [PATCH 20/20] fix failing Cadence tests & remove debug tests --- cadence/tests/evm_revertible_random_tests.cdc | 64 ------------------- .../tests/scripts/evm_revertible_random.cdc | 16 ----- cadence/tests/test_helpers.cdc | 10 +-- cadence/tests/wrap_and_mint_tests.cdc | 22 ++++--- .../src/test/TestCadenceRandomConsumer.sol | 29 --------- 5 files changed, 14 insertions(+), 127 deletions(-) delete mode 100644 cadence/tests/evm_revertible_random_tests.cdc delete mode 100644 cadence/tests/scripts/evm_revertible_random.cdc delete mode 100644 solidity/src/test/TestCadenceRandomConsumer.sol diff --git a/cadence/tests/evm_revertible_random_tests.cdc b/cadence/tests/evm_revertible_random_tests.cdc deleted file mode 100644 index 8ae3dac..0000000 --- a/cadence/tests/evm_revertible_random_tests.cdc +++ /dev/null @@ -1,64 +0,0 @@ -import Test -import BlockchainHelpers -import "test_helpers.cdc" - -import "EVM" - -access(all) let serviceAccount = Test.serviceAccount() - -access(all) var coaAddress: String = "" -access(all) var testAddress: String = "" - -access(all) -fun setup() { - // Create & fund a CadenceOwnedAccount - let coaRes = executeTransaction( - "./transactions/create_coa.cdc", - [100.0], - serviceAccount - ) - Test.expect(coaRes, Test.beSucceeded()) - - // Extract COA address from event - let coaEvts = Test.eventsOfType(Type()) - let coaEvt = coaEvts[0] as! EVM.CadenceOwnedAccountCreated - coaAddress = coaEvt.address - log("COA address: ".concat(coaAddress)) - - // Deploy WFLOW - let testDeployRes = executeTransaction( - "./transactions/deploy.cdc", - [testBytecode, UInt64(15_000_000), 0.0], - serviceAccount - ) - Test.expect(testDeployRes, Test.beSucceeded()) - - // Extract test address from event - var txnExecEvts = Test.eventsOfType(Type()) - let testEvt = txnExecEvts[2] as! EVM.TransactionExecuted - testAddress = testEvt.contractAddress - - log("Test address: ".concat(testAddress)) -} - -access(all) -fun testGetRevertibleRandomSucceeds() { - let a = getEVMRevertibleRandom(coaHost: serviceAccount.address, testAddress: EVM.addressFromString(testAddress)) - moveBlock() - let b = getEVMRevertibleRandom(coaHost: serviceAccount.address, testAddress: EVM.addressFromString(testAddress)) - moveBlock() - let c = getEVMRevertibleRandom(coaHost: serviceAccount.address, testAddress: EVM.addressFromString(testAddress)) - moveBlock() - let d = getEVMRevertibleRandom(coaHost: serviceAccount.address, testAddress: EVM.addressFromString(testAddress)) - moveBlock() - let e = getEVMRevertibleRandom(coaHost: serviceAccount.address, testAddress: EVM.addressFromString(testAddress)) - moveBlock() - let f = getEVMRevertibleRandom(coaHost: serviceAccount.address, testAddress: EVM.addressFromString(testAddress)) - log(String.join([a.toString(), b.toString(), c.toString(), d.toString(), e.toString(), f.toString()], separator: ", ")) - // Test.assert(a != b || a != c || b != c, message: "getEVMRevertibleRandom should return different values") -} - -access(all) -fun getEVMRevertibleRandom(coaHost: Address, testAddress: EVM.EVMAddress): UInt64 { - return 0 -} \ No newline at end of file diff --git a/cadence/tests/scripts/evm_revertible_random.cdc b/cadence/tests/scripts/evm_revertible_random.cdc deleted file mode 100644 index 2f0beab..0000000 --- a/cadence/tests/scripts/evm_revertible_random.cdc +++ /dev/null @@ -1,16 +0,0 @@ -import "EVM" - -access(all) -fun main(coaHost: Address, testAddress: EVM.EVMAddress): UInt64 { - let coa = getAuthAccount(coaHost).storage - .borrow(from: /storage/evm)! - let res = coa.call( - to: testAddress, - data: EVM.encodeABIWithSignature("getRevertibleRandomInRange(uint64,uint64)", [UInt64(0), UInt64(1000)]), - gasLimit: 15_000_000, - value: EVM.Balance(attoflow: 0) - ) - assert(res.status == EVM.Status.successful, message: "getRevertibleRandomInRange failed") - let decoded = EVM.decodeABI(types: [Type()], data: res.data) - return decoded[0] as! UInt64 -} diff --git a/cadence/tests/test_helpers.cdc b/cadence/tests/test_helpers.cdc index 8fe156d..43607aa 100644 --- a/cadence/tests/test_helpers.cdc +++ b/cadence/tests/test_helpers.cdc @@ -1,9 +1,8 @@ import Test // Bytecode constants -access(all) let wflowBytecode = "6080604052600436106100ae5763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166306fdde0381146100b8578063095ea7b31461014257806318160ddd1461017a57806323b872dd146101a15780632e1a7d4d146101cb578063313ce567146101e357806370a082311461020e57806395d89b411461022f578063a9059cbb14610244578063d0e30db0146100ae578063dd62ed3e14610268575b6100b661028f565b005b3480156100c457600080fd5b506100cd6102e7565b6040805160208082528351818301528351919283929083019185019080838360005b838110156101075781810151838201526020016100ef565b50505050905090810190601f1680156101345780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561014e57600080fd5b50610166600160a060020a0360043516602435610375565b604080519115158252519081900360200190f35b34801561018657600080fd5b5061018f6103df565b60408051918252519081900360200190f35b3480156101ad57600080fd5b50610166600160a060020a03600435811690602435166044356103ed565b3480156101d757600080fd5b506100b6600435610533565b3480156101ef57600080fd5b506101f86105e3565b6040805160ff9092168252519081900360200190f35b34801561021a57600080fd5b5061018f600160a060020a03600435166105ec565b34801561023b57600080fd5b506100cd6105fe565b34801561025057600080fd5b50610166600160a060020a0360043516602435610658565b34801561027457600080fd5b5061018f600160a060020a036004358116906024351661066c565b600160a060020a033316600081815260036020908152604091829020805434908101909155825190815291517fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9281900390910190a2565b6000805460408051602060026001851615610100026000190190941693909304601f8101849004840282018401909252818152929183018282801561036d5780601f106103425761010080835404028352916020019161036d565b820191906000526020600020905b81548152906001019060200180831161035057829003601f168201915b505050505081565b600160a060020a03338116600081815260046020908152604080832094871680845294825280832086905580518681529051929493927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a350600192915050565b600160a060020a0330163190565b600160a060020a03831660009081526003602052604081205482111561041257600080fd5b33600160a060020a031684600160a060020a03161415801561045c5750600160a060020a038085166000908152600460209081526040808320339094168352929052205460001914155b156104c257600160a060020a038085166000908152600460209081526040808320339094168352929052205482111561049457600080fd5b600160a060020a03808516600090815260046020908152604080832033909416835292905220805483900390555b600160a060020a03808516600081815260036020908152604080832080548890039055938716808352918490208054870190558351868152935191937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929081900390910190a35060019392505050565b600160a060020a03331660009081526003602052604090205481111561055857600080fd5b600160a060020a033316600081815260036020526040808220805485900390555183156108fc0291849190818181858888f193505050501580156105a0573d6000803e3d6000fd5b50604080518281529051600160a060020a033316917f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65919081900360200190a250565b60025460ff1681565b60036020526000908152604090205481565b60018054604080516020600284861615610100026000190190941693909304601f8101849004840282018401909252818152929183018282801561036d5780601f106103425761010080835404028352916020019161036d565b60006106653384846103ed565b9392505050565b6004602090815260009283526040808420909152908252902054815600a165627a7a72305820e1e0e82b179f331bf99f3294d4266cb1da578c59c07c2de6693f8cb10226617a0029" -access(all) let erc721Bytecode = "60806040523480156200001157600080fd5b506040516200181b3803806200181b833981016040819052620000349162000208565b338585600062000045838262000332565b50600162000054828262000332565b5050506001600160a01b0381166200008657604051631e4fbdf760e01b81526000600482015260240160405180910390fd5b6200009181620000d1565b50600780546001600160a01b039485166001600160a01b0319918216179091556008929092556009805491909316911617905550506000600a55620003fe565b600680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200014b57600080fd5b81516001600160401b038082111562000168576200016862000123565b604051601f8301601f19908116603f0116810190828211818310171562000193576200019362000123565b8160405283815260209250866020858801011115620001b157600080fd5b600091505b83821015620001d55785820183015181830184015290820190620001b6565b6000602085830101528094505050505092915050565b80516001600160a01b03811681146200020357600080fd5b919050565b600080600080600060a086880312156200022157600080fd5b85516001600160401b03808211156200023957600080fd5b6200024789838a0162000139565b965060208801519150808211156200025e57600080fd5b506200026d8882890162000139565b9450506200027e60408701620001eb565b9250606086015191506200029560808701620001eb565b90509295509295909350565b600181811c90821680620002b657607f821691505b602082108103620002d757634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200032d576000816000526020600020601f850160051c81016020861015620003085750805b601f850160051c820191505b81811015620003295782815560010162000314565b5050505b505050565b81516001600160401b038111156200034e576200034e62000123565b62000366816200035f8454620002a1565b84620002dd565b602080601f8311600181146200039e5760008415620003855750858301515b600019600386901b1c1916600185901b17855562000329565b600085815260208120601f198616915b82811015620003cf57888601518255948401946001909101908401620003ae565b5085821015620003ee5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b61140d806200040e6000396000f3fe608060405234801561001057600080fd5b50600436106101375760003560e01c806370a08231116100b8578063a22cb4651161007c578063a22cb4651461026b578063b88d4fde1461027e578063bdb4b84814610291578063c87b56dd1461029a578063e985e9c5146102ad578063f2fde38b146102c057600080fd5b806370a0823114610224578063715018a6146102375780638bca6d161461023f5780638da5cb5b1461025257806395d89b411461026357600080fd5b806318160ddd116100ff57806318160ddd146101c157806323b872dd146101d857806338af3eed146101eb57806342842e0e146101fe5780636352211e1461021157600080fd5b806301ffc9a71461013c57806306fdde0314610164578063081812fc14610179578063095ea7b3146101a45780631249c58b146101b9575b600080fd5b61014f61014a366004610fb5565b6102d3565b60405190151581526020015b60405180910390f35b61016c610325565b60405161015b9190611022565b61018c610187366004611035565b6103b7565b6040516001600160a01b03909116815260200161015b565b6101b76101b236600461106a565b6103e0565b005b6101b76103ef565b6101ca600a5481565b60405190815260200161015b565b6101b76101e6366004611094565b6103f9565b60095461018c906001600160a01b031681565b6101b761020c366004611094565b610489565b61018c61021f366004611035565b6104a9565b6101ca6102323660046110d0565b6104b4565b6101b76104fc565b60075461018c906001600160a01b031681565b6006546001600160a01b031661018c565b61016c61050e565b6101b76102793660046110f9565b61051d565b6101b761028c366004611146565b610528565b6101ca60085481565b61016c6102a8366004611035565b610540565b61014f6102bb366004611222565b6105b5565b6101b76102ce3660046110d0565b6105e3565b60006001600160e01b031982166380ac58cd60e01b148061030457506001600160e01b03198216635b5e139f60e01b145b8061031f57506301ffc9a760e01b6001600160e01b03198316145b92915050565b60606000805461033490611255565b80601f016020809104026020016040519081016040528092919081815260200182805461036090611255565b80156103ad5780601f10610382576101008083540402835291602001916103ad565b820191906000526020600020905b81548152906001019060200180831161039057829003601f168201915b5050505050905090565b60006103c282610621565b506000828152600460205260409020546001600160a01b031661031f565b6103eb82823361065a565b5050565b6103f7610667565b565b6001600160a01b03821661042857604051633250574960e11b8152600060048201526024015b60405180910390fd5b6000610435838333610746565b9050836001600160a01b0316816001600160a01b031614610483576040516364283d7b60e01b81526001600160a01b038086166004830152602482018490528216604482015260640161041f565b50505050565b6104a483838360405180602001604052806000815250610528565b505050565b600061031f82610621565b60006001600160a01b0382166104e0576040516322718ad960e21b81526000600482015260240161041f565b506001600160a01b031660009081526003602052604090205490565b61050461083f565b6103f7600061086c565b60606001805461033490611255565b6103eb3383836108be565b6105338484846103f9565b610483338585858561095d565b606061054b82610621565b50600061056360408051602081019091526000815290565b9050600081511161058357604051806020016040528060008152506105ae565b8061058d84610a88565b60405160200161059e92919061128f565b6040516020818303038152906040525b9392505050565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b6105eb61083f565b6001600160a01b03811661061557604051631e4fbdf760e01b81526000600482015260240161041f565b61061e8161086c565b50565b6000818152600260205260408120546001600160a01b03168061031f57604051637e27328960e01b81526004810184905260240161041f565b6104a48383836001610b1b565b61066f610c21565b6007546009546008546040516323b872dd60e01b81523360048201526001600160a01b03928316602482015260448101919091529116906323b872dd906064016020604051808303816000875af19250505080156106ea575060408051601f3d908101601f191682019092526106e7918101906112be565b60015b6107245760075460085460405163760a9bc360e11b81526001600160a01b039092166004830152336024830152604482015260640161041f565b50600a8054906000610735836112db565b91905055506103f733600a54610c62565b6000828152600260205260408120546001600160a01b039081169083161561077357610773818486610cc7565b6001600160a01b038116156107b157610790600085600080610b1b565b6001600160a01b038116600090815260036020526040902080546000190190555b6001600160a01b038516156107e0576001600160a01b0385166000908152600360205260409020805460010190555b60008481526002602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4949350505050565b6006546001600160a01b031633146103f75760405163118cdaa760e01b815233600482015260240161041f565b600680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6001600160a01b0382166108f057604051630b61174360e31b81526001600160a01b038316600482015260240161041f565b6001600160a01b03838116600081815260056020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6001600160a01b0383163b15610a8157604051630a85bd0160e11b81526001600160a01b0384169063150b7a029061099f908890889087908790600401611302565b6020604051808303816000875af19250505080156109da575060408051601f3d908101601f191682019092526109d79181019061133f565b60015b610a43573d808015610a08576040519150601f19603f3d011682016040523d82523d6000602084013e610a0d565b606091505b508051600003610a3b57604051633250574960e11b81526001600160a01b038516600482015260240161041f565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b14610a7f57604051633250574960e11b81526001600160a01b038516600482015260240161041f565b505b5050505050565b60606000610a9583610d2b565b600101905060008167ffffffffffffffff811115610ab557610ab5611130565b6040519080825280601f01601f191660200182016040528015610adf576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a8504945084610ae957509392505050565b8080610b2f57506001600160a01b03821615155b15610bf1576000610b3f84610621565b90506001600160a01b03831615801590610b6b5750826001600160a01b0316816001600160a01b031614155b8015610b7e5750610b7c81846105b5565b155b15610ba75760405163a9fbf51f60e01b81526001600160a01b038416600482015260240161041f565b8115610bef5783856001600160a01b0316826001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45b505b5050600090815260046020526040902080546001600160a01b0319166001600160a01b0392909216919091179055565b6000610c2b610e03565b9050610c3860028261135c565b67ffffffffffffffff1660010361061e576040516351d099d960e11b815260040160405180910390fd5b6001600160a01b038216610c8c57604051633250574960e11b81526000600482015260240161041f565b6000610c9a83836000610746565b90506001600160a01b038116156104a4576040516339e3563760e11b81526000600482015260240161041f565b610cd2838383610f3c565b6104a4576001600160a01b038316610d0057604051637e27328960e01b81526004810182905260240161041f565b60405163177e802f60e01b81526001600160a01b03831660048201526024810182905260440161041f565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b8310610d6a5772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef81000000008310610d96576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc100008310610db457662386f26fc10000830492506010015b6305f5e1008310610dcc576305f5e100830492506008015b6127108310610de057612710830492506004015b60648310610df2576064830492506002015b600a831061031f5760010192915050565b60408051600481526024810182526020810180516001600160e01b0316630382fd5960e51b1790529051600091829182916801000000000000000191610e499190611391565b600060405180830381855afa9150503d8060008114610e84576040519150601f19603f3d011682016040523d82523d6000602084013e610e89565b606091505b509150915081610f1e5760405162461bcd60e51b815260206004820152605460248201527f556e7375636365737366756c2063616c6c20746f20436164656e63652041726360448201527f68207072652d636f6d70696c65207768656e206665746368696e672072657665606482015273393a34b13632903930b73237b690373ab6b132b960611b608482015260a40161041f565b600081806020019051810190610f3491906113ad565b949350505050565b60006001600160a01b03831615801590610f345750826001600160a01b0316846001600160a01b03161480610f765750610f7684846105b5565b80610f345750506000908152600460205260409020546001600160a01b03908116911614919050565b6001600160e01b03198116811461061e57600080fd5b600060208284031215610fc757600080fd5b81356105ae81610f9f565b60005b83811015610fed578181015183820152602001610fd5565b50506000910152565b6000815180845261100e816020860160208601610fd2565b601f01601f19169290920160200192915050565b6020815260006105ae6020830184610ff6565b60006020828403121561104757600080fd5b5035919050565b80356001600160a01b038116811461106557600080fd5b919050565b6000806040838503121561107d57600080fd5b6110868361104e565b946020939093013593505050565b6000806000606084860312156110a957600080fd5b6110b28461104e565b92506110c06020850161104e565b9150604084013590509250925092565b6000602082840312156110e257600080fd5b6105ae8261104e565b801515811461061e57600080fd5b6000806040838503121561110c57600080fd5b6111158361104e565b91506020830135611125816110eb565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b6000806000806080858703121561115c57600080fd5b6111658561104e565b93506111736020860161104e565b925060408501359150606085013567ffffffffffffffff8082111561119757600080fd5b818701915087601f8301126111ab57600080fd5b8135818111156111bd576111bd611130565b604051601f8201601f19908116603f011681019083821181831017156111e5576111e5611130565b816040528281528a60208487010111156111fe57600080fd5b82602086016020830137600060208483010152809550505050505092959194509250565b6000806040838503121561123557600080fd5b61123e8361104e565b915061124c6020840161104e565b90509250929050565b600181811c9082168061126957607f821691505b60208210810361128957634e487b7160e01b600052602260045260246000fd5b50919050565b600083516112a1818460208801610fd2565b8351908301906112b5818360208801610fd2565b01949350505050565b6000602082840312156112d057600080fd5b81516105ae816110eb565b6000600182016112fb57634e487b7160e01b600052601160045260246000fd5b5060010190565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061133590830184610ff6565b9695505050505050565b60006020828403121561135157600080fd5b81516105ae81610f9f565b600067ffffffffffffffff8084168061138557634e487b7160e01b600052601260045260246000fd5b92169190910692915050565b600082516113a3818460208701610fd2565b9190910192915050565b6000602082840312156113bf57600080fd5b815167ffffffffffffffff811681146105ae57600080fdfea26469706673582212204919ee1872648a1b85d633af14a8f8c7163d176b6699f75fe4e22d677fc562ae64736f6c63430008180033" -access(all) let testBytecode = "608060405234801561001057600080fd5b50611210806100206000396000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c80635461f2e41461005c578063bc26d8241461008c578063d59fd63c1461009f578063f8413b07146100c2578063fc177f7f146100d8575b600080fd5b61006f61006a366004610fac565b6100eb565b6040516001600160401b0390911681526020015b60405180910390f35b61006f61009a366004610fe5565b610100565b6100b26100ad366004610fe5565b61010b565b6040519015158152602001610083565b6100ca610189565b604051908152602001610083565b61006f6100e6366004610ffe565b610198565b60006100f783836101ad565b90505b92915050565b60006100fa82610225565b600080610119600184611056565b600054909150811061012e5750600092915050565b600080828154811061014257610142611069565b90600052602060002090600302019050600061015c6102df565b600283015490915060ff16158015610180575081546001600160401b038083169116105b95945050505050565b600061019361040e565b905090565b60006101a584848461054f565b949350505050565b6000806101b861060d565b6040516020016101ca91815260200190565b60408051601f1981840301815282825243602084015292506000910160408051601f1981840301815282820190915260008083526020830152915061021081848461066a565b61021b81878761079d565b9695505050505050565b600080610231836108cc565b60405160200161024391815260200190565b60408051601f198184030181528282526020830186905292506000910160408051601f1981840301815282820190915260008083526020830152915061028a81848461066a565b600061029582610a11565b6040516001600160401b038216815290915086907fe3e452ff947e18cea0f62f23d405e522ac808f69346c5f59ddc4bd722ac10d039060200160405180910390a295945050505050565b60408051600481526024810182526020810180516001600160e01b03166329f43eb360e11b179052905160009182918291680100000000000000019161032591906110af565b600060405180830381855afa9150503d8060008114610360576040519150601f19603f3d011682016040523d82523d6000602084013e610365565b606091505b5091509150816103f85760405162461bcd60e51b815260206004820152604d60248201527f556e7375636365737366756c2063616c6c20746f20436164656e63652041726360448201527f68207072652d636f6d70696c65207768656e206665746368696e6720466c6f7760648201526c08189b1bd8dac81a195a59da1d609a1b608482015260a4015b60405180910390fd5b6000818060200190518101906101a591906110bb565b600180546000918261041f836110df565b919050555060006001549050600060405180606001604052806104406102df565b6001600160401b0390811682524360208084019190915260006040938401819052805460018101825590805284517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5636003909202918201805467ffffffffffffffff191691909416908117909355848201517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5648201819055858501517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e565909201805460ff19169215159290921790915583519283529082015291925083917f7886956edccde10901843c3e51fc26016455e9248e210a29c2a57ead63ad226e910160405180910390a250919050565b60008061055b856108cc565b60405160200161056d91815260200190565b60408051601f198184030181528282526020830188905292506000910160408051601f198184030181528282019091526000808352602083015291506105b481848461066a565b60006105c182888861079d565b6040516001600160401b038216815290915088907fe3e452ff947e18cea0f62f23d405e522ac808f69346c5f59ddc4bd722ac10d039060200160405180910390a2979650505050505050565b600080610618610a6e565b6001600160401b03169050604061062d610a6e565b6001600160401b0316901b176080610643610a6e565b6001600160401b0316901b1760c0610659610a6e565b6001600160401b0316901b17919050565b6010825110156106f05760405162461bcd60e51b815260206004820152604560248201527f4174206c65617374203136206279746573206f6620656e74726f70792073686f60448201527f756c642062652075736564207768656e20696e697469616c697a696e67207468606482015264652050524760d81b608482015260a4016103ef565b600082826040516020016107059291906110f8565b604051602081830303815290604052905060008180519060200120905061074e8160405160200161073891815260200190565b6040516020818303038152906040526000610b89565b6001600160401b03168552604080516020810183905261077f91016040516020818303038152906040526008610b89565b6001600160401b0316602086015261079685610c41565b5050505050565b6000826001600160401b0316826001600160401b0316116108005760405162461bcd60e51b815260206004820152601c60248201527f4d6178206d7573742062652067726561746572207468616e206d696e0000000060448201526064016103ef565b600061080c848461110d565b9050600061081982610cda565b9050600061083460016001600160401b03841681901b611056565b9050600061084483610100611134565b6001600160401b03169050600080600061085d8b610d10565b90505b8481169150866001600160401b0316826001600160401b031611156108b3576001600160401b0386161c82610894816110df565b9350508383036108ae576108a78b610d10565b9050600092505b610860565b6108bd828b611168565b9b9a5050505050505050505050565b6000806108da600184611056565b600054909150811061095f5760405162461bcd60e51b815260206004820152604260248201527f496e76616c69642072657175657374204944202d2076616c756520657863656560448201527f647320746865206e756d626572206f66206578697374696e6720726571756573606482015261747360f01b608482015260a4016103ef565b600080828154811061097357610973611069565b9060005260206000209060030201905061098c81610d72565b60028101805460ff1916600117905580546000906109b2906001600160401b0316610e5b565b82546001840154604080516001600160401b0390931683526020830191909152810182905290915085907f01f207584638dfbb3f1d85bba3809672fcb07a3d2e291308293ba78b7f1984909060600160405180910390a2949350505050565b6000610a1c82610c41565b5080516020820180516001600160401b03808216909452601783901b6a7fffffffffffffff80000016909218601181901c657fffffffffff1618601a83901c643fffffffff1683181892831690520190565b60408051600481526024810182526020810180516001600160e01b0316630382fd5960e51b1790529051600091829182916801000000000000000191610ab491906110af565b600060405180830381855afa9150503d8060008114610aef576040519150601f19603f3d011682016040523d82523d6000602084013e610af4565b606091505b5091509150816103f85760405162461bcd60e51b815260206004820152605460248201527f556e7375636365737366756c2063616c6c20746f20436164656e63652041726360448201527f68207072652d636f6d70696c65207768656e206665746368696e672072657665606482015273393a34b13632903930b73237b690373ab6b132b960611b608482015260a4016103ef565b6000610b96826008611188565b83511015610bdc5760405162461bcd60e51b8152602060048201526013602482015272092dcecc2d8d2c840c4f2e8ca40d8cadccee8d606b1b60448201526064016103ef565b6000805b6008811015610c395784610bf48286611188565b81518110610c0457610c04611069565b602001015160f81c60f81b60f81c60ff166008836001600160401b0316901b1791508080610c31906110df565b915050610be0565b509392505050565b80516001600160401b0316151580610c65575060208101516001600160401b031615155b610cd75760405162461bcd60e51b815260206004820152603860248201527f50524720696e697469616c2073746174652069732030202d206d75737420626560448201527f20696e697469616c697a6564206173206e6f6e2d7a65726f000000000000000060648201526084016103ef565b50565b6000805b6001600160401b038316156100fa576001836001600160401b0316901c92508080610d089061119b565b915050610cde565b600080610d1c83610a11565b6001600160401b031690506040610d3284610a11565b6001600160401b0316901b176080610d4984610a11565b6001600160401b0316901b1760c0610d6084610a11565b6001600160401b0316901b1792915050565b600281015460ff1615610dc75760405162461bcd60e51b815260206004820152601960248201527f5265717565737420616c72656164792066756c66696c6c65640000000000000060448201526064016103ef565b610dcf6102df565b81546001600160401b03918216911610610cd75760405162461bcd60e51b815260206004820152604160248201527f43616e6e6f742066756c66696c6c207265717565737420756e74696c2073756260448201527f73657175656e7420466c6f77206e6574776f726b20626c6f636b2068656967686064820152601d60fa1b608482015260a4016103ef565b6040516001600160401b038216602482015260009081908190680100000000000000019060440160408051601f198184030181529181526020820180516001600160e01b0316633c53afdf60e11b17905251610eb791906110af565b600060405180830381855afa9150503d8060008114610ef2576040519150601f19603f3d011682016040523d82523d6000602084013e610ef7565b606091505b509150915081610f815760405162461bcd60e51b815260206004820152604960248201527f556e7375636365737366756c2063616c6c20746f20436164656e63652041726360448201527f68207072652d636f6d70696c65207768656e206665746368696e672072616e646064820152686f6d20736f7572636560b81b608482015260a4016103ef565b60008180602001905181019061018091906111c1565b6001600160401b0381168114610cd757600080fd5b60008060408385031215610fbf57600080fd5b8235610fca81610f97565b91506020830135610fda81610f97565b809150509250929050565b600060208284031215610ff757600080fd5b5035919050565b60008060006060848603121561101357600080fd5b83359250602084013561102581610f97565b9150604084013561103581610f97565b809150509250925092565b634e487b7160e01b600052601160045260246000fd5b818103818111156100fa576100fa611040565b634e487b7160e01b600052603260045260246000fd5b6000815160005b818110156110a05760208185018101518683015201611086565b50600093019283525090919050565b60006100f7828461107f565b6000602082840312156110cd57600080fd5b81516110d881610f97565b9392505050565b6000600182016110f1576110f1611040565b5060010190565b60006101a5611107838661107f565b8461107f565b6001600160401b0382811682821603908082111561112d5761112d611040565b5092915050565b60006001600160401b038084168061115c57634e487b7160e01b600052601260045260246000fd5b92169190910492915050565b6001600160401b0381811683821601908082111561112d5761112d611040565b808201808211156100fa576100fa611040565b60006001600160401b038083168181036111b7576111b7611040565b6001019392505050565b6000602082840312156111d357600080fd5b505191905056fea2646970667358221220f8c9a068ce5c9c1b3f61e3676f66b60a38347f8e7f4830594074a9377b82688564736f6c63430008130033" +access(all) let wflowBytecode = "60c0604052600c60808190526b5772617070656420466c6f7760a01b60a090815261002d916000919061007a565b506040805180820190915260058082526457464c4f5760d81b602090920191825261005a9160019161007a565b506002805460ff1916601217905534801561007457600080fd5b50610115565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106100bb57805160ff19168380011785556100e8565b828001600101855582156100e8579182015b828111156100e85782518255916020019190600101906100cd565b506100f49291506100f8565b5090565b61011291905b808211156100f457600081556001016100fe565b90565b6106e3806101246000396000f3fe60806040526004361061009c5760003560e01c8063313ce56711610064578063313ce5671461021157806370a082311461023c57806395d89b411461026f578063a9059cbb14610284578063d0e30db01461009c578063dd62ed3e146102bd5761009c565b806306fdde03146100a6578063095ea7b31461013057806318160ddd1461017d57806323b872dd146101a45780632e1a7d4d146101e7575b6100a46102f8565b005b3480156100b257600080fd5b506100bb610347565b6040805160208082528351818301528351919283929083019185019080838360005b838110156100f55781810151838201526020016100dd565b50505050905090810190601f1680156101225780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561013c57600080fd5b506101696004803603604081101561015357600080fd5b506001600160a01b0381351690602001356103d5565b604080519115158252519081900360200190f35b34801561018957600080fd5b5061019261043b565b60408051918252519081900360200190f35b3480156101b057600080fd5b50610169600480360360608110156101c757600080fd5b506001600160a01b0381358116916020810135909116906040013561043f565b3480156101f357600080fd5b506100a46004803603602081101561020a57600080fd5b5035610573565b34801561021d57600080fd5b50610226610608565b6040805160ff9092168252519081900360200190f35b34801561024857600080fd5b506101926004803603602081101561025f57600080fd5b50356001600160a01b0316610611565b34801561027b57600080fd5b506100bb610623565b34801561029057600080fd5b50610169600480360360408110156102a757600080fd5b506001600160a01b03813516906020013561067d565b3480156102c957600080fd5b50610192600480360360408110156102e057600080fd5b506001600160a01b0381358116916020013516610691565b33600081815260036020908152604091829020805434908101909155825190815291517fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9281900390910190a2565b6000805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156103cd5780601f106103a2576101008083540402835291602001916103cd565b820191906000526020600020905b8154815290600101906020018083116103b057829003601f168201915b505050505081565b3360008181526004602090815260408083206001600160a01b038716808552908352818420869055815186815291519394909390927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925928290030190a350600192915050565b4790565b6001600160a01b03831660009081526003602052604081205482111561046457600080fd5b6001600160a01b03841633148015906104a257506001600160a01b038416600090815260046020908152604080832033845290915290205460001914155b15610502576001600160a01b03841660009081526004602090815260408083203384529091529020548211156104d757600080fd5b6001600160a01b03841660009081526004602090815260408083203384529091529020805483900390555b6001600160a01b03808516600081815260036020908152604080832080548890039055938716808352918490208054870190558351868152935191937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929081900390910190a35060019392505050565b3360009081526003602052604090205481111561058f57600080fd5b33600081815260036020526040808220805485900390555183156108fc0291849190818181858888f193505050501580156105ce573d6000803e3d6000fd5b5060408051828152905133917f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65919081900360200190a250565b60025460ff1681565b60036020526000908152604090205481565b60018054604080516020600284861615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156103cd5780601f106103a2576101008083540402835291602001916103cd565b600061068a33848461043f565b9392505050565b60046020908152600092835260408084209091529082529020548156fea265627a7a7231582092a6eff3c9232bde55997efc6d8d256f5875b16304694b39e740dcabf78f802964736f6c63430005110032" +access(all) let erc721Bytecode = "60806040523480156200001157600080fd5b506040516200181b3803806200181b833981016040819052620000349162000208565b338585600062000045838262000332565b50600162000054828262000332565b5050506001600160a01b0381166200008657604051631e4fbdf760e01b81526000600482015260240160405180910390fd5b6200009181620000d1565b50600780546001600160a01b039485166001600160a01b0319918216179091556008929092556009805491909316911617905550506000600a55620003fe565b600680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200014b57600080fd5b81516001600160401b038082111562000168576200016862000123565b604051601f8301601f19908116603f0116810190828211818310171562000193576200019362000123565b8160405283815260209250866020858801011115620001b157600080fd5b600091505b83821015620001d55785820183015181830184015290820190620001b6565b6000602085830101528094505050505092915050565b80516001600160a01b03811681146200020357600080fd5b919050565b600080600080600060a086880312156200022157600080fd5b85516001600160401b03808211156200023957600080fd5b6200024789838a0162000139565b965060208801519150808211156200025e57600080fd5b506200026d8882890162000139565b9450506200027e60408701620001eb565b9250606086015191506200029560808701620001eb565b90509295509295909350565b600181811c90821680620002b657607f821691505b602082108103620002d757634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200032d576000816000526020600020601f850160051c81016020861015620003085750805b601f850160051c820191505b81811015620003295782815560010162000314565b5050505b505050565b81516001600160401b038111156200034e576200034e62000123565b62000366816200035f8454620002a1565b84620002dd565b602080601f8311600181146200039e5760008415620003855750858301515b600019600386901b1c1916600185901b17855562000329565b600085815260208120601f198616915b82811015620003cf57888601518255948401946001909101908401620003ae565b5085821015620003ee5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b61140d806200040e6000396000f3fe608060405234801561001057600080fd5b50600436106101375760003560e01c806370a08231116100b8578063a22cb4651161007c578063a22cb4651461026b578063b88d4fde1461027e578063bdb4b84814610291578063c87b56dd1461029a578063e985e9c5146102ad578063f2fde38b146102c057600080fd5b806370a0823114610224578063715018a6146102375780638bca6d161461023f5780638da5cb5b1461025257806395d89b411461026357600080fd5b806318160ddd116100ff57806318160ddd146101c157806323b872dd146101d857806338af3eed146101eb57806342842e0e146101fe5780636352211e1461021157600080fd5b806301ffc9a71461013c57806306fdde0314610164578063081812fc14610179578063095ea7b3146101a45780631249c58b146101b9575b600080fd5b61014f61014a366004610fb5565b6102d3565b60405190151581526020015b60405180910390f35b61016c610325565b60405161015b9190611022565b61018c610187366004611035565b6103b7565b6040516001600160a01b03909116815260200161015b565b6101b76101b236600461106a565b6103e0565b005b6101b76103ef565b6101ca600a5481565b60405190815260200161015b565b6101b76101e6366004611094565b6103f9565b60095461018c906001600160a01b031681565b6101b761020c366004611094565b610489565b61018c61021f366004611035565b6104a9565b6101ca6102323660046110d0565b6104b4565b6101b76104fc565b60075461018c906001600160a01b031681565b6006546001600160a01b031661018c565b61016c61050e565b6101b76102793660046110f9565b61051d565b6101b761028c366004611146565b610528565b6101ca60085481565b61016c6102a8366004611035565b610540565b61014f6102bb366004611222565b6105b5565b6101b76102ce3660046110d0565b6105e3565b60006001600160e01b031982166380ac58cd60e01b148061030457506001600160e01b03198216635b5e139f60e01b145b8061031f57506301ffc9a760e01b6001600160e01b03198316145b92915050565b60606000805461033490611255565b80601f016020809104026020016040519081016040528092919081815260200182805461036090611255565b80156103ad5780601f10610382576101008083540402835291602001916103ad565b820191906000526020600020905b81548152906001019060200180831161039057829003601f168201915b5050505050905090565b60006103c282610621565b506000828152600460205260409020546001600160a01b031661031f565b6103eb82823361065a565b5050565b6103f7610667565b565b6001600160a01b03821661042857604051633250574960e11b8152600060048201526024015b60405180910390fd5b6000610435838333610746565b9050836001600160a01b0316816001600160a01b031614610483576040516364283d7b60e01b81526001600160a01b038086166004830152602482018490528216604482015260640161041f565b50505050565b6104a483838360405180602001604052806000815250610528565b505050565b600061031f82610621565b60006001600160a01b0382166104e0576040516322718ad960e21b81526000600482015260240161041f565b506001600160a01b031660009081526003602052604090205490565b61050461083f565b6103f7600061086c565b60606001805461033490611255565b6103eb3383836108be565b6105338484846103f9565b610483338585858561095d565b606061054b82610621565b50600061056360408051602081019091526000815290565b9050600081511161058357604051806020016040528060008152506105ae565b8061058d84610a88565b60405160200161059e92919061128f565b6040516020818303038152906040525b9392505050565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b6105eb61083f565b6001600160a01b03811661061557604051631e4fbdf760e01b81526000600482015260240161041f565b61061e8161086c565b50565b6000818152600260205260408120546001600160a01b03168061031f57604051637e27328960e01b81526004810184905260240161041f565b6104a48383836001610b1b565b61066f610c21565b6007546009546008546040516323b872dd60e01b81523360048201526001600160a01b03928316602482015260448101919091529116906323b872dd906064016020604051808303816000875af19250505080156106ea575060408051601f3d908101601f191682019092526106e7918101906112be565b60015b6107245760075460085460405163760a9bc360e11b81526001600160a01b039092166004830152336024830152604482015260640161041f565b50600a8054906000610735836112db565b91905055506103f733600a54610c62565b6000828152600260205260408120546001600160a01b039081169083161561077357610773818486610cc7565b6001600160a01b038116156107b157610790600085600080610b1b565b6001600160a01b038116600090815260036020526040902080546000190190555b6001600160a01b038516156107e0576001600160a01b0385166000908152600360205260409020805460010190555b60008481526002602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4949350505050565b6006546001600160a01b031633146103f75760405163118cdaa760e01b815233600482015260240161041f565b600680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6001600160a01b0382166108f057604051630b61174360e31b81526001600160a01b038316600482015260240161041f565b6001600160a01b03838116600081815260056020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6001600160a01b0383163b15610a8157604051630a85bd0160e11b81526001600160a01b0384169063150b7a029061099f908890889087908790600401611302565b6020604051808303816000875af19250505080156109da575060408051601f3d908101601f191682019092526109d79181019061133f565b60015b610a43573d808015610a08576040519150601f19603f3d011682016040523d82523d6000602084013e610a0d565b606091505b508051600003610a3b57604051633250574960e11b81526001600160a01b038516600482015260240161041f565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b14610a7f57604051633250574960e11b81526001600160a01b038516600482015260240161041f565b505b5050505050565b60606000610a9583610d2b565b600101905060008167ffffffffffffffff811115610ab557610ab5611130565b6040519080825280601f01601f191660200182016040528015610adf576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a8504945084610ae957509392505050565b8080610b2f57506001600160a01b03821615155b15610bf1576000610b3f84610621565b90506001600160a01b03831615801590610b6b5750826001600160a01b0316816001600160a01b031614155b8015610b7e5750610b7c81846105b5565b155b15610ba75760405163a9fbf51f60e01b81526001600160a01b038416600482015260240161041f565b8115610bef5783856001600160a01b0316826001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45b505b5050600090815260046020526040902080546001600160a01b0319166001600160a01b0392909216919091179055565b6000610c2b610e03565b9050610c3860028261135c565b67ffffffffffffffff1660010361061e576040516351d099d960e11b815260040160405180910390fd5b6001600160a01b038216610c8c57604051633250574960e11b81526000600482015260240161041f565b6000610c9a83836000610746565b90506001600160a01b038116156104a4576040516339e3563760e11b81526000600482015260240161041f565b610cd2838383610f3c565b6104a4576001600160a01b038316610d0057604051637e27328960e01b81526004810182905260240161041f565b60405163177e802f60e01b81526001600160a01b03831660048201526024810182905260440161041f565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b8310610d6a5772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef81000000008310610d96576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc100008310610db457662386f26fc10000830492506010015b6305f5e1008310610dcc576305f5e100830492506008015b6127108310610de057612710830492506004015b60648310610df2576064830492506002015b600a831061031f5760010192915050565b60408051600481526024810182526020810180516001600160e01b0316630382fd5960e51b1790529051600091829182916801000000000000000191610e499190611391565b600060405180830381855afa9150503d8060008114610e84576040519150601f19603f3d011682016040523d82523d6000602084013e610e89565b606091505b509150915081610f1e5760405162461bcd60e51b815260206004820152605460248201527f556e7375636365737366756c2063616c6c20746f20436164656e63652041726360448201527f68207072652d636f6d70696c65207768656e206665746368696e672072657665606482015273393a34b13632903930b73237b690373ab6b132b960611b608482015260a40161041f565b600081806020019051810190610f3491906113ad565b949350505050565b60006001600160a01b03831615801590610f345750826001600160a01b0316846001600160a01b03161480610f765750610f7684846105b5565b80610f345750506000908152600460205260409020546001600160a01b03908116911614919050565b6001600160e01b03198116811461061e57600080fd5b600060208284031215610fc757600080fd5b81356105ae81610f9f565b60005b83811015610fed578181015183820152602001610fd5565b50506000910152565b6000815180845261100e816020860160208601610fd2565b601f01601f19169290920160200192915050565b6020815260006105ae6020830184610ff6565b60006020828403121561104757600080fd5b5035919050565b80356001600160a01b038116811461106557600080fd5b919050565b6000806040838503121561107d57600080fd5b6110868361104e565b946020939093013593505050565b6000806000606084860312156110a957600080fd5b6110b28461104e565b92506110c06020850161104e565b9150604084013590509250925092565b6000602082840312156110e257600080fd5b6105ae8261104e565b801515811461061e57600080fd5b6000806040838503121561110c57600080fd5b6111158361104e565b91506020830135611125816110eb565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b6000806000806080858703121561115c57600080fd5b6111658561104e565b93506111736020860161104e565b925060408501359150606085013567ffffffffffffffff8082111561119757600080fd5b818701915087601f8301126111ab57600080fd5b8135818111156111bd576111bd611130565b604051601f8201601f19908116603f011681019083821181831017156111e5576111e5611130565b816040528281528a60208487010111156111fe57600080fd5b82602086016020830137600060208483010152809550505050505092959194509250565b6000806040838503121561123557600080fd5b61123e8361104e565b915061124c6020840161104e565b90509250929050565b600181811c9082168061126957607f821691505b60208210810361128957634e487b7160e01b600052602260045260246000fd5b50919050565b600083516112a1818460208801610fd2565b8351908301906112b5818360208801610fd2565b01949350505050565b6000602082840312156112d057600080fd5b81516105ae816110eb565b6000600182016112fb57634e487b7160e01b600052601160045260246000fd5b5060010190565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061133590830184610ff6565b9695505050505050565b60006020828403121561135157600080fd5b81516105ae81610f9f565b600067ffffffffffffffff8084168061138557634e487b7160e01b600052601260045260246000fd5b92169190910692915050565b600082516113a3818460208701610fd2565b9190910192915050565b6000602082840312156113bf57600080fd5b815167ffffffffffffffff811681146105ae57600080fdfea2646970667358221220859d8cb88597efba0ae5690919e0bd43747ee03f464470c2b6f1c0b3f9bb454f64736f6c63430008180033" /* --- Getters --- */ @@ -17,11 +16,6 @@ fun getERC721Bytecode(): String { return erc721Bytecode } -access(all) -fun getTestBytecode(): String { - return testBytecode -} - access(all) fun moveBlock() { let res = _executeTransaction( diff --git a/cadence/tests/wrap_and_mint_tests.cdc b/cadence/tests/wrap_and_mint_tests.cdc index fde9ff2..d8120b4 100644 --- a/cadence/tests/wrap_and_mint_tests.cdc +++ b/cadence/tests/wrap_and_mint_tests.cdc @@ -24,7 +24,6 @@ fun setup() { let coaEvts = Test.eventsOfType(Type()) let coaEvt = coaEvts[0] as! EVM.CadenceOwnedAccountCreated coaAddress = coaEvt.address - log("COA address: ".concat(coaAddress)) // Deploy WFLOW let wflowDeployRes = executeTransaction( @@ -52,7 +51,7 @@ fun setup() { constructorArgs )) // Append the encoded constructor args to the compiled bytecode - let finalBytecode = getERC721Bytecode().concat(argsBytecode) + let finalBytecode = String.join([getERC721Bytecode(), argsBytecode], separator: "") let erc721DeployRes = executeTransaction( "./transactions/deploy.cdc", [finalBytecode, UInt64(15_000_000), 0.0], @@ -64,9 +63,6 @@ fun setup() { txnExecEvts = Test.eventsOfType(Type()) let erc721Evt = txnExecEvts[3] as! EVM.TransactionExecuted erc721Address = erc721Evt.contractAddress - - log("WFLOW address: ".concat(wflowAddress)) - log("ERC721 address: ".concat(erc721Address)) } access(all) @@ -74,15 +70,21 @@ fun testWrapAndMintSucceeds() { let user = Test.createAccount() mintFlow(to: user, amount: 10.0) - wrapAndMintUntilSuccess(signer: user, wflow: wflowAddress, erc721: erc721Address) + // Executes the wrap_and_mint.cdc transaction + // - Creates a COA + // - Funds the COA with FLOW to cover mint cost + // - Wraps FLOW as WFLOW + // - Approves ERC721 contract to mint + // - Mints ERC721 <- may fail so we retry here until success (can't mock CadenceArch calls in Cadence tests atm) + wrapAndMintUntilSuccess(iter: 5, signer: user, wflow: wflowAddress, erc721: erc721Address) } access(all) -fun wrapAndMintUntilSuccess(signer: Test.TestAccount, wflow: String, erc721: String) { +fun wrapAndMintUntilSuccess(iter: Int, signer: Test.TestAccount, wflow: String, erc721: String) { var i = 0 var success = false - while i < 50 { - let res: Test.TransactionResult = executeTransaction( + while i < iter { + let res = executeTransaction( "../transactions/bundled/wrap_and_mint.cdc", [wflow, erc721], signer @@ -95,5 +97,5 @@ fun wrapAndMintUntilSuccess(signer: Test.TestAccount, wflow: String, erc721: Str moveBlock() } } - Test.assertEqual(true, success) + Test.assert(success) } \ No newline at end of file diff --git a/solidity/src/test/TestCadenceRandomConsumer.sol b/solidity/src/test/TestCadenceRandomConsumer.sol deleted file mode 100644 index 950b6f2..0000000 --- a/solidity/src/test/TestCadenceRandomConsumer.sol +++ /dev/null @@ -1,29 +0,0 @@ -// SPDX-License-Identifier: Unlicense -pragma solidity 0.8.19; - -import {CadenceRandomConsumer} from "onflow/random-coin-toss/solidity/src/CadenceRandomConsumer.sol"; - -/** - * @dev This contract extends CadenceRandomConsumer to expose internal functions for testing. - */ -contract TestCadenceRandomConsumer is CadenceRandomConsumer { - // Expose internal _getRevertibleRandomInRange function for testing - function getRevertibleRandomInRange(uint64 min, uint64 max) public view returns (uint64) { - return _getRevertibleRandomInRange(min, max); - } - - // Expose internal _requestRandomness function for testing - function requestRandomness() public returns (uint256) { - return _requestRandomness(); - } - - // Expose internal _fulfillRandomRequest function for testing - function fulfillRandomRequest(uint256 requestId) public returns (uint64) { - return _fulfillRandomRequest(requestId); - } - - // Expose internal _fulfillRandomInRange function for testing - function fulfillRandomInRange(uint256 requestId, uint64 min, uint64 max) public returns (uint64) { - return _fulfillRandomInRange(requestId, min, max); - } -}