Skip to content
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
add crafting example with gmc2
  • Loading branch information
allan-almeida-imtbl committed Sep 6, 2024
commit ec9dabb2561e1848e0b01748e181cb1504bd6709
176 changes: 176 additions & 0 deletions test/multicall/Crafting2.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
// SPDX-License-Identifier: Apache 2.0
pragma solidity 0.8.19;

import "forge-std/Test.sol";
import "forge-std/console.sol";

import {DeployOperatorAllowlist} from "../utils/DeployAllowlistProxy.sol";
import {OperatorAllowlistUpgradeable} from "../../contracts/allowlist/OperatorAllowlistUpgradeable.sol";
import {ImmutableERC1155} from "../../contracts/token/erc1155/preset/ImmutableERC1155.sol";
import {ImmutableERC721} from "../../contracts/token/erc721/preset/ImmutableERC721.sol";
import {GuardedMulticaller2} from "../../contracts/multicall/GuardedMulticaller2.sol";

import {SigUtils} from "./SigUtils.t.sol";

contract Crafting2Test is Test {
OperatorAllowlistUpgradeable public operatorAllowlist;
ImmutableERC1155 public game1155;
ImmutableERC721 public game721;
GuardedMulticaller2 public multicaller;
SigUtils public sigUtils;

uint256 public imtblPrivateKey = 1;
uint256 public gameStudioPrivateKey = 2;
uint256 public signingAuthorityPrivateKey = 3;
uint256 public playerPrivateKey = 4;

address public imtbl = vm.addr(imtblPrivateKey);
address public gameStudio = vm.addr(gameStudioPrivateKey);
address public signingAuthority = vm.addr(signingAuthorityPrivateKey);
address public player = vm.addr(playerPrivateKey);

address public proxyAddr;

string public multicallerName = "multicaller-name";
string public multicallerVersion = "multicaller-version";

function setUp() public {
DeployOperatorAllowlist deployScript = new DeployOperatorAllowlist();
proxyAddr = deployScript.run(imtbl, imtbl, imtbl);
operatorAllowlist = OperatorAllowlistUpgradeable(proxyAddr);

assertTrue(operatorAllowlist.hasRole(operatorAllowlist.REGISTRAR_ROLE(), imtbl));

game1155 = new ImmutableERC1155(
gameStudio, "test1155", "test-base-uri", "test-contract-uri", address(operatorAllowlist), gameStudio, 0
);

vm.prank(gameStudio);
game1155.grantMinterRole(gameStudio);
assertTrue(game1155.hasRole(game1155.MINTER_ROLE(), gameStudio));

game721 = new ImmutableERC721(
gameStudio, "test721", "TST", "test-base-uri", "test-contract-uri", address(operatorAllowlist), gameStudio, 0
);

// Deploy game studio's multicaller contract
multicaller = new GuardedMulticaller2(gameStudio, multicallerName, multicallerVersion);
assertTrue(multicaller.hasRole(multicaller.DEFAULT_ADMIN_ROLE(), gameStudio));

// Add multicaller to operator allowlist
address[] memory allowlistTargets = new address[](1);
allowlistTargets[0] = address(multicaller);

vm.prank(imtbl);
operatorAllowlist.addAddressesToAllowlist(allowlistTargets);
assertTrue(operatorAllowlist.isAllowlisted(address(multicaller)));

// Grant minter role to the game studio
vm.startPrank(gameStudio);
game721.grantMinterRole(gameStudio);
assertTrue(game721.hasRole(game721.MINTER_ROLE(), gameStudio));

// Grant minter role to the multicaller contract
game721.grantMinterRole(address(multicaller));
assertTrue(game721.hasRole(game721.MINTER_ROLE(), address(multicaller)));
vm.stopPrank();

// Grant signer role to signing authority
vm.prank(gameStudio);
multicaller.grantMulticallSignerRole(signingAuthority);
assertTrue(multicaller.hasRole(multicaller.MULTICALL_SIGNER_ROLE(), signingAuthority));

sigUtils = new SigUtils(multicallerName, multicallerVersion, address(multicaller));
}

function testCraft() public {
// Game studio mints 10 of tokenID 1 on 1155 to player
vm.prank(gameStudio);
game1155.safeMint(player, 1, 10, "");
assertTrue(game1155.balanceOf(player, 1) == 10);

// Game studio mints 10 of tokenID 2 on 1155 to player
vm.prank(gameStudio);
game1155.safeMint(player, 2, 10, "");
assertTrue(game1155.balanceOf(player, 2) == 10);

// Perform a craft using the Multicaller
// - burn 1 of 1155 tokenID 1
// - burn 2 of 1155 tokenID 2
// - mint 1 721 to player

bytes32 referenceID = keccak256("testCraft:1");

uint256[] memory ids = new uint256[](2);
ids[0] = 1;
ids[1] = 2;

uint256[] memory values = new uint256[](2);
values[0] = 1;
values[1] = 2;

// Construct signature
GuardedMulticaller2.Call[] memory calls = new GuardedMulticaller2.Call[](2);

calls[0] = GuardedMulticaller2.Call(
address(game1155),
"burnBatch(address,uint256[],uint256[])",
abi.encode(player, ids, values)
);

calls[1] = GuardedMulticaller2.Call(
address(game721),
"safeMint(address,uint256)",
abi.encode(player, uint256(1))
);

uint256 deadline = block.timestamp + 10;

bytes32 structHash = sigUtils.hashTypedData(referenceID, calls, deadline);

vm.startPrank(signingAuthority);
(uint8 v, bytes32 r, bytes32 s) = vm.sign(signingAuthorityPrivateKey, structHash);
bytes memory signature = abi.encodePacked(r, s, v);
vm.stopPrank();

// Give multicaller approve to burn
vm.startPrank(player);
game1155.setApprovalForAll(address(multicaller), true);
assertTrue(game1155.isApprovedForAll(player, address(multicaller)));

multicaller.execute(signingAuthority, referenceID, calls, deadline, signature);
vm.stopPrank();

assertTrue(game1155.balanceOf(player, 1) == 9);
assertTrue(game1155.balanceOf(player, 2) == 8);
assertTrue(game721.balanceOf(player) == 1);
}

// function testSignature() public {
// bytes32 referenceID = keccak256("testCraft:1");

// address[] memory targets = new address[](2);
// targets[0] = address(game1155);
// targets[1] = address(game721);

// bytes[] memory data = new bytes[](2);

// uint256[] memory ids = new uint256[](2);
// ids[0] = 1;
// ids[1] = 2;

// uint256[] memory values = new uint256[](2);
// values[0] = 1;
// values[1] = 2;

// data[0] = abi.encodeWithSignature("burnBatch(address,uint256[],uint256[])", player, ids, values);
// data[1] = abi.encodeWithSignature("safeMint(address,uint256)", player, 1);

// uint256 deadline = block.timestamp + 10;

// // Construct signature
// bytes32 structHash = sigUtils.hashTypedData(referenceID, calls, deadline);

// console.log("structHash", structHash);
// }
}
22 changes: 11 additions & 11 deletions test/multicall/GuardedMulticaller2.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,13 @@ contract GuardedMulticaller2Test is Test {
calls[0] = GuardedMulticaller2.Call(
address(target),
"succeedWithUint256(uint256)",
abi.encodePacked(uint256(42))
abi.encode(uint256(42))
);
calls[1] = GuardedMulticaller2.Call(address(target), "succeed()", "");
calls[2] = GuardedMulticaller2.Call(
address(target1),
"succeedWithUint256(uint256)",
abi.encodePacked(uint256(42))
abi.encode(uint256(42))
);

bytes32 digest = sigUtils.hashTypedData(ref, calls, deadline);
Expand All @@ -80,7 +80,7 @@ contract GuardedMulticaller2Test is Test {
calls[0] = GuardedMulticaller2.Call(
address(target),
"succeedWithUint256(uint256)",
abi.encodePacked(uint256(42))
abi.encode(uint256(42))
);

bytes32 digest = sigUtils.hashTypedData(ref, calls, deadline);
Expand All @@ -99,7 +99,7 @@ contract GuardedMulticaller2Test is Test {
calls[0] = GuardedMulticaller2.Call(
address(target),
"succeedWithUint256(uint256)",
abi.encodePacked(uint256(42))
abi.encode(uint256(42))
);

bytes32 digest = sigUtils.hashTypedData(ref, calls, deadline);
Expand All @@ -118,7 +118,7 @@ contract GuardedMulticaller2Test is Test {
calls[0] = GuardedMulticaller2.Call(
address(target),
"succeedWithUint256(uint256)",
abi.encodePacked(uint256(42))
abi.encode(uint256(42))
);

bytes32 digest = sigUtils.hashTypedData(ref, calls, deadline);
Expand Down Expand Up @@ -149,7 +149,7 @@ contract GuardedMulticaller2Test is Test {
bytes32 ref = "ref";
uint256 deadline = block.timestamp + 1;
GuardedMulticaller2.Call[] memory calls = new GuardedMulticaller2.Call[](1);
calls[0] = GuardedMulticaller2.Call(address(0), "succeedWithUint256(uint256)", abi.encodePacked(uint256(42)));
calls[0] = GuardedMulticaller2.Call(address(0), "succeedWithUint256(uint256)", abi.encode(uint256(42)));

bytes32 digest = sigUtils.hashTypedData(ref, calls, deadline);
(uint8 v, bytes32 r, bytes32 s) = vm.sign(signerPk, digest);
Expand All @@ -168,7 +168,7 @@ contract GuardedMulticaller2Test is Test {
calls[0] = GuardedMulticaller2.Call(
address(target),
"succeedWithUint256(uint256)",
abi.encodePacked(uint256(42))
abi.encode(uint256(42))
);

bytes32 digest = sigUtils.hashTypedData(ref, calls, deadline);
Expand All @@ -188,7 +188,7 @@ contract GuardedMulticaller2Test is Test {
calls[0] = GuardedMulticaller2.Call(
address(target),
"succeedWithUint256(uint256)",
abi.encodePacked(uint256(42))
abi.encode(uint256(42))
);

bytes32 digest = sigUtils.hashTypedData(ref, calls, deadline);
Expand Down Expand Up @@ -222,7 +222,7 @@ contract GuardedMulticaller2Test is Test {
calls[0] = GuardedMulticaller2.Call(
address(target),
"succeedWithUint256(uint256)",
abi.encodePacked(uint256(42))
abi.encode(uint256(42))
);

bytes32 digest = sigUtils.hashTypedData(ref, calls, deadline);
Expand Down Expand Up @@ -250,7 +250,7 @@ contract GuardedMulticaller2Test is Test {
bytes32 ref = keccak256("ref");
uint256 deadline = block.timestamp + 1;
GuardedMulticaller2.Call[] memory calls = new GuardedMulticaller2.Call[](1);
calls[0] = GuardedMulticaller2.Call(address(target), "revertWithData(uint256)", abi.encodePacked(uint256(42)));
calls[0] = GuardedMulticaller2.Call(address(target), "revertWithData(uint256)", abi.encode(uint256(42)));

bytes32 digest = sigUtils.hashTypedData(ref, calls, deadline);
(uint8 v, bytes32 r, bytes32 s) = vm.sign(signerPk, digest);
Expand All @@ -265,7 +265,7 @@ contract GuardedMulticaller2Test is Test {
bytes32 ref = keccak256("ref");
uint256 deadline = block.timestamp + 1;
GuardedMulticaller2.Call[] memory calls = new GuardedMulticaller2.Call[](1);
calls[0] = GuardedMulticaller2.Call(address(target), "", abi.encodePacked(uint256(42)));
calls[0] = GuardedMulticaller2.Call(address(target), "", abi.encode(uint256(42)));

bytes32 digest = sigUtils.hashTypedData(ref, calls, deadline);
(uint8 v, bytes32 r, bytes32 s) = vm.sign(signerPk, digest);
Expand Down