From 73483ed6320e820dcd29b219644f3a07ab69ed8d Mon Sep 17 00:00:00 2001 From: jaybuidl Date: Thu, 12 Jun 2025 22:01:50 +0100 Subject: [PATCH 01/13] feat: whitelisted USDC and USDC.e on Arbitrum with 000 cap --- contracts/deploy/00-escrow.ts | 8 + contracts/deployments/arbitrum/USDC.json | 1391 +++++++++++++++++ contracts/deployments/arbitrum/USDCe.json | 804 ++++++++++ contracts/scripts/dotenv.sh | 15 + .../scripts/generateDeploymentsMarkdown.sh | 2 + 5 files changed, 2220 insertions(+) create mode 100644 contracts/deployments/arbitrum/USDC.json create mode 100644 contracts/deployments/arbitrum/USDCe.json create mode 100755 contracts/scripts/dotenv.sh diff --git a/contracts/deploy/00-escrow.ts b/contracts/deploy/00-escrow.ts index f5e741e..b7902f7 100644 --- a/contracts/deploy/00-escrow.ts +++ b/contracts/deploy/00-escrow.ts @@ -50,11 +50,19 @@ const deploy: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { const escrow = (await ethers.getContract("EscrowUniversal")) as EscrowUniversal; const WETH = await deployments.get("WETH"); const DAI = await deployments.get("DAI"); + const USDC = await deployments.getOrNull("USDC"); + const USDCe = await deployments.getOrNull("USDCe"); // USDC.e (Bridged USDC) const caps = { [ethers.ZeroAddress]: ethers.parseUnits("0.3"), [WETH.address]: ethers.parseUnits("0.3"), [DAI.address]: ethers.parseUnits("1000"), }; + if (USDC) { + caps[USDC.address] = ethers.parseUnits("1000", 6); + } + if (USDCe) { + caps[USDCe.address] = ethers.parseUnits("1000", 6); + } for (const [token, cap] of Object.entries(caps)) { console.log("Setting cap for", token, cap); await escrow.changeAmountCap(token, cap); diff --git a/contracts/deployments/arbitrum/USDC.json b/contracts/deployments/arbitrum/USDC.json new file mode 100644 index 0000000..9c9a1ae --- /dev/null +++ b/contracts/deployments/arbitrum/USDC.json @@ -0,0 +1,1391 @@ +{ + "address": "0xaf88d065e77c8cc2239327c5edb3a432268e5831", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "authorizer", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "nonce", + "type": "bytes32" + } + ], + "name": "AuthorizationCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "authorizer", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "nonce", + "type": "bytes32" + } + ], + "name": "AuthorizationUsed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "_account", + "type": "address" + } + ], + "name": "Blacklisted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "newBlacklister", + "type": "address" + } + ], + "name": "BlacklisterChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "burner", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Burn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "newMasterMinter", + "type": "address" + } + ], + "name": "MasterMinterChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "minterAllowedAmount", + "type": "uint256" + } + ], + "name": "MinterConfigured", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldMinter", + "type": "address" + } + ], + "name": "MinterRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "Pause", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "newAddress", + "type": "address" + } + ], + "name": "PauserChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "newRescuer", + "type": "address" + } + ], + "name": "RescuerChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "_account", + "type": "address" + } + ], + "name": "UnBlacklisted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "Unpause", + "type": "event" + }, + { + "inputs": [], + "name": "CANCEL_AUTHORIZATION_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "DOMAIN_SEPARATOR", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PERMIT_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "RECEIVE_WITH_AUTHORIZATION_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TRANSFER_WITH_AUTHORIZATION_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "authorizer", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "nonce", + "type": "bytes32" + } + ], + "name": "authorizationState", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_account", + "type": "address" + } + ], + "name": "blacklist", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "blacklister", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "authorizer", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "nonce", + "type": "bytes32" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "cancelAuthorization", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "authorizer", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "nonce", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "cancelAuthorization", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "internalType": "uint256", + "name": "minterAllowedAmount", + "type": "uint256" + } + ], + "name": "configureMinter", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "currency", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "decrement", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "increment", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "tokenName", + "type": "string" + }, + { + "internalType": "string", + "name": "tokenSymbol", + "type": "string" + }, + { + "internalType": "string", + "name": "tokenCurrency", + "type": "string" + }, + { + "internalType": "uint8", + "name": "tokenDecimals", + "type": "uint8" + }, + { + "internalType": "address", + "name": "newMasterMinter", + "type": "address" + }, + { + "internalType": "address", + "name": "newPauser", + "type": "address" + }, + { + "internalType": "address", + "name": "newBlacklister", + "type": "address" + }, + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "newName", + "type": "string" + } + ], + "name": "initializeV2", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "lostAndFound", + "type": "address" + } + ], + "name": "initializeV2_1", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "accountsToBlacklist", + "type": "address[]" + }, + { + "internalType": "string", + "name": "newSymbol", + "type": "string" + } + ], + "name": "initializeV2_2", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_account", + "type": "address" + } + ], + "name": "isBlacklisted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "isMinter", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "masterMinter", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "minter", + "type": "address" + } + ], + "name": "minterAllowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pauser", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "permit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "permit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "validAfter", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "validBefore", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "nonce", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "receiveWithAuthorization", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "validAfter", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "validBefore", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "nonce", + "type": "bytes32" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "receiveWithAuthorization", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "minter", + "type": "address" + } + ], + "name": "removeMinter", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "tokenContract", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "rescueERC20", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "rescuer", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "validAfter", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "validBefore", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "nonce", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "transferWithAuthorization", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "validAfter", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "validBefore", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "nonce", + "type": "bytes32" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "transferWithAuthorization", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_account", + "type": "address" + } + ], + "name": "unBlacklist", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newBlacklister", + "type": "address" + } + ], + "name": "updateBlacklister", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newMasterMinter", + "type": "address" + } + ], + "name": "updateMasterMinter", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newPauser", + "type": "address" + } + ], + "name": "updatePauser", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newRescuer", + "type": "address" + } + ], + "name": "updateRescuer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + } + ] +} diff --git a/contracts/deployments/arbitrum/USDCe.json b/contracts/deployments/arbitrum/USDCe.json new file mode 100644 index 0000000..239bf4d --- /dev/null +++ b/contracts/deployments/arbitrum/USDCe.json @@ -0,0 +1,804 @@ +{ + "address": "0xff970a61a04b1ca14834a43f5de4533ebddb5cc8", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Blacklisted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "newBlacklister", + "type": "address" + } + ], + "name": "BlacklisterChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnerChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "pauser", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousPauser", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newPauser", + "type": "address" + } + ], + "name": "PauserChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "UnBlacklisted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "pauser", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "inputs": [], + "name": "DOMAIN_SEPARATOR", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "blacklist", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "blacklister", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "bridgeBurn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_l1Address", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "bridgeInit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "bridgeMint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "changeOwner", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "gatewayAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals", + "type": "uint8" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_gatewayAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "_l1Address", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals", + "type": "uint8" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "isBlacklisted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "l1Address", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pauser", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "permit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "setPauser", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "transferAndCall", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "unBlacklist", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newBlacklister", + "type": "address" + } + ], + "name": "updateBlacklister", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ] +} diff --git a/contracts/scripts/dotenv.sh b/contracts/scripts/dotenv.sh new file mode 100755 index 0000000..7953bfc --- /dev/null +++ b/contracts/scripts/dotenv.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash + +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" + +varKey=$1 + +if [ -z "$varKey" ]; then + echo "Env variable name not provided. Exiting..." >&2 + exit 1 +fi + +node -e " + require('dotenv').config({ path: '"$SCRIPT_DIR"/../.env' }) + console.log(process.env.$varKey) +" | sed 1d diff --git a/contracts/scripts/generateDeploymentsMarkdown.sh b/contracts/scripts/generateDeploymentsMarkdown.sh index 973aaee..614bacd 100755 --- a/contracts/scripts/generateDeploymentsMarkdown.sh +++ b/contracts/scripts/generateDeploymentsMarkdown.sh @@ -8,6 +8,8 @@ IGNORED_ARTIFACTS=( "PNK.json" "DAI.json" "WETH.json" + "USDC.json" + "USDCe.json" "RandomizerOracle.json" "_Implementation.json" "_Proxy.json" From 282a30d593b26245097b8d0a1e8acbbd7331650f Mon Sep 17 00:00:00 2001 From: jaybuidl Date: Mon, 23 Jun 2025 17:11:31 +0100 Subject: [PATCH 02/13] feat: whitelisted PNK on Arbitrum --- contracts/deploy/00-escrow.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/contracts/deploy/00-escrow.ts b/contracts/deploy/00-escrow.ts index b7902f7..4c30f88 100644 --- a/contracts/deploy/00-escrow.ts +++ b/contracts/deploy/00-escrow.ts @@ -50,6 +50,7 @@ const deploy: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { const escrow = (await ethers.getContract("EscrowUniversal")) as EscrowUniversal; const WETH = await deployments.get("WETH"); const DAI = await deployments.get("DAI"); + const PNK = await deployments.getOrNull("PNK"); const USDC = await deployments.getOrNull("USDC"); const USDCe = await deployments.getOrNull("USDCe"); // USDC.e (Bridged USDC) const caps = { @@ -57,6 +58,9 @@ const deploy: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { [WETH.address]: ethers.parseUnits("0.3"), [DAI.address]: ethers.parseUnits("1000"), }; + if (PNK) { + caps[PNK.address] = ethers.parseUnits("100000"); // 100,000 PNK + } if (USDC) { caps[USDC.address] = ethers.parseUnits("1000", 6); } From 50110c14fb5353bd284a12ed8ddd4af0ac2d0d56 Mon Sep 17 00:00:00 2001 From: unknownunknown1 Date: Wed, 25 Jun 2025 18:17:32 +1000 Subject: [PATCH 03/13] feat(Escrow): add custom buyer option --- contracts/foundry.toml | 3 +- contracts/src/EscrowUniversal.sol | 30 +++++++++++++++++++ contracts/test/EscrowUniversal.t.sol | 43 ++++++++++++++++++++++++++++ 3 files changed, 75 insertions(+), 1 deletion(-) diff --git a/contracts/foundry.toml b/contracts/foundry.toml index ff6d90c..4c47604 100644 --- a/contracts/foundry.toml +++ b/contracts/foundry.toml @@ -1,4 +1,5 @@ [profile.default] src = 'src' out = 'out' -libs = ['../node_modules', 'lib'] \ No newline at end of file +libs = ['../node_modules', 'lib'] +via_ir = true \ No newline at end of file diff --git a/contracts/src/EscrowUniversal.sol b/contracts/src/EscrowUniversal.sol index 09acdd1..1dd9966 100644 --- a/contracts/src/EscrowUniversal.sol +++ b/contracts/src/EscrowUniversal.sol @@ -186,6 +186,36 @@ contract EscrowUniversal is IEscrow, IArbitrableV2 { ); } + function createERC20TransactionCustomBuyer( + uint256 _amount, + IERC20 _token, + uint256 _deadline, + string memory _transactionUri, + address payable _buyer, + address payable _seller + ) external shouldNotExceedCap(_token, _amount) returns (uint256 transactionID) { + // Transfers token from sender wallet to contract. Note that the amount is provided by the caller, not by the buyer. + if (!_token.safeTransferFrom(msg.sender, address(this), _amount)) revert TokenTransferFailed(); + Transaction storage transaction = transactions.push(); + transaction.buyer = _buyer; + transaction.seller = _seller; + transaction.amount = _amount; + transaction.token = _token; + transaction.deadline = _deadline; + + transactionID = transactions.length - 1; + + emit ERC20TransactionCreated( + transactionID, + _transactionUri, + _buyer, + _seller, + _token, + _amount, + transaction.deadline + ); + } + /// @inheritdoc IEscrow function pay(uint256 _transactionID, uint256 _amount) external override { Transaction storage transaction = transactions[_transactionID]; diff --git a/contracts/test/EscrowUniversal.t.sol b/contracts/test/EscrowUniversal.t.sol index e01d936..c7c199a 100644 --- a/contracts/test/EscrowUniversal.t.sol +++ b/contracts/test/EscrowUniversal.t.sol @@ -380,6 +380,49 @@ contract EscrowUniversalTest is Test { assertEq(escrowToken.balanceOf(seller), 0, "Balance of seller should be 0"); } + function test_createERC20TransactionCustomBuyer() public { + uint256 deadline = block.timestamp + txTimeout; + uint256 txId; + vm.prank(buyer); + vm.expectEmit(true, true, true, true); + // Pay a bit less to differ between tests + emit ERC20TransactionCreated(txId, txUri, other, seller, escrowToken, 0.4 ether, deadline); + escrow.createERC20TransactionCustomBuyer(0.4 ether, escrowToken, deadline, txUri, payable(other), payable(seller)); + + ( + address escrowBuyer, + address escrowSeller, + uint256 amount, + uint256 settlementBuyer, + uint256 settlementSeller, + uint256 escrowdeadline, + uint256 disputeId, + uint256 buyerFee, + uint256 sellerFee, + uint256 lastFeePaymentTime, + Status status, + IERC20 token + ) = escrow.transactions(txId); + + assertEq(escrowBuyer, other, "Wrong custom buyer address"); + assertEq(escrowSeller, seller, "Wrong seller address"); + assertEq(amount, 0.4 ether, "Wrong escrow amount"); + assertEq(settlementBuyer, 0, "settlementBuyer should be 0"); + assertEq(settlementSeller, 0, "settlementSeller should be 0"); + assertEq(escrowdeadline, block.timestamp + 1000, "Wrong deadline"); + assertEq(disputeId, 0, "disputeId should be 0"); + assertEq(sellerFee, 0, "sellerFee should be 0"); + assertEq(lastFeePaymentTime, 0, "lastFeePaymentTime should be 0"); + assertEq(uint256(status), uint256(Status.NoDispute), "Wrong status"); + assertEq(address(token), address(escrowToken), "Wrong token address"); + assertEq(escrow.getTransactionCount(), 1, "Wrong transaction count"); + + assertEq(escrowToken.balanceOf(address(escrow)), 0.4 ether, "Wrong token balance of the escrow"); + assertEq(escrowToken.balanceOf(buyer), 0.6 ether, "Wrong token balance of buyer"); // tx creator + assertEq(escrowToken.balanceOf(seller), 0, "Balance of seller should be 0"); + assertEq(escrowToken.balanceOf(other), 0, "Balance of custom buyer should be 0"); // custom buyer did not have balance of his own + } + function test_createNativeTransaction_approvalMissing() public { uint256 deadline = block.timestamp + txTimeout; From b2c695962e8786872701267ce0027112f6ac4c89 Mon Sep 17 00:00:00 2001 From: unknownunknown1 Date: Sun, 29 Jun 2025 16:11:05 +1000 Subject: [PATCH 04/13] feat(Escrow): add function to interface --- contracts/src/EscrowUniversal.sol | 3 ++- contracts/src/interfaces/IEscrow.sol | 17 +++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/contracts/src/EscrowUniversal.sol b/contracts/src/EscrowUniversal.sol index 1dd9966..144b134 100644 --- a/contracts/src/EscrowUniversal.sol +++ b/contracts/src/EscrowUniversal.sol @@ -186,6 +186,7 @@ contract EscrowUniversal is IEscrow, IArbitrableV2 { ); } + /// @inheritdoc IEscrow function createERC20TransactionCustomBuyer( uint256 _amount, IERC20 _token, @@ -193,7 +194,7 @@ contract EscrowUniversal is IEscrow, IArbitrableV2 { string memory _transactionUri, address payable _buyer, address payable _seller - ) external shouldNotExceedCap(_token, _amount) returns (uint256 transactionID) { + ) external override shouldNotExceedCap(_token, _amount) returns (uint256 transactionID) { // Transfers token from sender wallet to contract. Note that the amount is provided by the caller, not by the buyer. if (!_token.safeTransferFrom(msg.sender, address(this), _amount)) revert TokenTransferFailed(); Transaction storage transaction = transactions.push(); diff --git a/contracts/src/interfaces/IEscrow.sol b/contracts/src/interfaces/IEscrow.sol index 252df49..f7902a6 100644 --- a/contracts/src/interfaces/IEscrow.sol +++ b/contracts/src/interfaces/IEscrow.sol @@ -99,6 +99,23 @@ interface IEscrow { address payable _seller ) external returns (uint256 transactionID); + /// @dev Create an ERC20 transaction with custom buyer address. + /// @param _amount The amount of tokens in this transaction. + /// @param _token The ERC20 token contract. + /// @param _deadline Time after which a party can automatically execute the arbitrable transaction. + /// @param _transactionUri The IPFS Uri Hash of the transaction. + /// @param _buyer Buyer's address. + /// @param _seller The recipient of the transaction. + /// @return transactionID The index of the transaction. + function createERC20TransactionCustomBuyer( + uint256 _amount, + IERC20 _token, + uint256 _deadline, + string memory _transactionUri, + address payable _buyer, + address payable _seller + ) external returns (uint256 transactionID); + /// @dev Pay seller. To be called if the good or service is provided. /// @param _transactionID The index of the transaction. /// @param _amount Amount to pay in wei. From 3ca5c73d4900b31d0fa691bae79219513dbe13bf Mon Sep 17 00:00:00 2001 From: jaybuidl Date: Sun, 20 Jul 2025 02:31:18 +0200 Subject: [PATCH 05/13] chore: bumped @kleros/kleros-v2-contracts to pick up the latest devnet contracts --- contracts/package.json | 2 +- web/package.json | 2 +- yarn.lock | 538 +++++++++++++++++++++++------------------ 3 files changed, 304 insertions(+), 238 deletions(-) diff --git a/contracts/package.json b/contracts/package.json index e36bb65..39ce3b2 100644 --- a/contracts/package.json +++ b/contracts/package.json @@ -83,7 +83,7 @@ "typescript": "^5.7.3" }, "dependencies": { - "@kleros/kleros-v2-contracts": "^0.9.3", + "@kleros/kleros-v2-contracts": "^0.10.0", "@openzeppelin/contracts": "^5.3.0" } } diff --git a/web/package.json b/web/package.json index e7a9134..1d99e4e 100644 --- a/web/package.json +++ b/web/package.json @@ -47,7 +47,7 @@ "devDependencies": { "@graphql-codegen/cli": "^4.0.1", "@graphql-codegen/client-preset": "^4.6.2", - "@kleros/kleros-v2-contracts": "^0.9.3", + "@kleros/kleros-v2-contracts": "^0.10.0", "@types/react": "^18.2.59", "@types/react-dom": "^18.2.18", "@types/react-modal": "^3.16.3", diff --git a/yarn.lock b/yarn.lock index 28d1a09..507f70f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -26,7 +26,7 @@ __metadata: languageName: node linkType: hard -"@adraffy/ens-normalize@npm:^1.10.1": +"@adraffy/ens-normalize@npm:^1.10.1, @adraffy/ens-normalize@npm:^1.11.0": version: 1.11.0 resolution: "@adraffy/ens-normalize@npm:1.11.0" checksum: 10/abef75f21470ea43dd6071168e092d2d13e38067e349e76186c78838ae174a46c3e18ca50921d05bea6ec3203074147c9e271f8cb6531d1c2c0e146f3199ddcb @@ -63,43 +63,16 @@ __metadata: languageName: node linkType: hard -"@arbitrum/nitro-contracts@npm:1.1.1": - version: 1.1.1 - resolution: "@arbitrum/nitro-contracts@npm:1.1.1" - dependencies: - "@offchainlabs/upgrade-executor": "npm:1.1.0-beta.0" - "@openzeppelin/contracts": "npm:4.5.0" - "@openzeppelin/contracts-upgradeable": "npm:4.5.2" - patch-package: "npm:^6.4.7" - checksum: 10/6ea79388bd8ed6de2fdb2e1334d37b520928732c86540eaebed1e21a9f2a04dbc11dbae89f06bd66a169130f9b54d90c9fe6ed45cd4d286bc28b4d77fd49c1f8 - languageName: node - linkType: hard - -"@arbitrum/nitro-contracts@npm:^1.0.0-beta.8": - version: 1.3.0 - resolution: "@arbitrum/nitro-contracts@npm:1.3.0" +"@arbitrum/nitro-contracts@npm:3.0.0": + version: 3.0.0 + resolution: "@arbitrum/nitro-contracts@npm:3.0.0" dependencies: "@offchainlabs/upgrade-executor": "npm:1.1.0-beta.0" - "@openzeppelin/contracts": "npm:4.5.0" - "@openzeppelin/contracts-upgradeable": "npm:4.5.2" + "@openzeppelin/contracts": "npm:4.7.3" + "@openzeppelin/contracts-upgradeable": "npm:4.7.3" patch-package: "npm:^6.4.7" - checksum: 10/cc931bf6d65f8249cfe0527b5e7be2bfb30c40ea8408320949db76e20076b91dcbb384f5b5fb997f303f1b4b83310a0f98a5382d4ec1a58be8cf92267d615121 - languageName: node - linkType: hard - -"@arbitrum/token-bridge-contracts@npm:1.1.2": - version: 1.1.2 - resolution: "@arbitrum/token-bridge-contracts@npm:1.1.2" - dependencies: - "@arbitrum/nitro-contracts": "npm:^1.0.0-beta.8" - "@offchainlabs/upgrade-executor": "npm:1.1.0-beta.0" - "@openzeppelin/contracts": "npm:4.8.3" - "@openzeppelin/contracts-upgradeable": "npm:4.8.3" - "@openzeppelin/upgrades-core": "npm:^1.24.1" - dependenciesMeta: - "@openzeppelin/upgrades-core": - optional: true - checksum: 10/d9a1b69db886e4d34f34f9b92dc226ee2add122328da9dc79a4046322a486a731f5992b8e22a0929b1bb717f9d1d1b60b43085fb952a50e955447b3d7aa1bf0c + solady: "npm:0.0.182" + checksum: 10/9f2ddd2871f86c23ab8c584fa9d205cc2a8de29dc1124544eb7b070a96e85a6301587902f0c86547e9be63716848da202a8cead01fbd884f73e0b0a01582ba81 languageName: node linkType: hard @@ -1965,28 +1938,20 @@ __metadata: languageName: node linkType: hard -"@bytecodealliance/preview2-shim@npm:0.17.0": - version: 0.17.0 - resolution: "@bytecodealliance/preview2-shim@npm:0.17.0" - checksum: 10/28a273227d8e8f2b61ad0260be612fd854ace756784c409c6ac4b65bf6b48426e6c058e45c07675303ef844a981fbdda7257df9833ca12bd3e5e4a0480ca5193 - languageName: node - linkType: hard - -"@chainlink/contracts@npm:^1.3.0": - version: 1.3.0 - resolution: "@chainlink/contracts@npm:1.3.0" +"@chainlink/contracts@npm:^1.4.0": + version: 1.4.0 + resolution: "@chainlink/contracts@npm:1.4.0" dependencies: - "@arbitrum/nitro-contracts": "npm:1.1.1" - "@arbitrum/token-bridge-contracts": "npm:1.1.2" - "@changesets/changelog-github": "npm:^0.5.0" - "@changesets/cli": "npm:~2.27.8" + "@arbitrum/nitro-contracts": "npm:3.0.0" + "@changesets/cli": "npm:~2.28.1" + "@changesets/get-github-info": "npm:^0.6.0" "@eth-optimism/contracts": "npm:0.6.0" - "@openzeppelin/contracts": "npm:4.9.3" - "@openzeppelin/contracts-upgradeable": "npm:4.9.3" + "@openzeppelin/contracts": "npm:4.9.6" + "@openzeppelin/contracts-upgradeable": "npm:4.9.6" "@scroll-tech/contracts": "npm:0.1.0" - "@zksync/contracts": "git+https://github.com/matter-labs/era-contracts.git#446d391d34bdb48255d5f8fef8a8248925fc98b9" - semver: "npm:^7.6.3" - checksum: 10/223e80492520cccad301ba360a27c11c73070cc8e9d03af73f68db987f9ad1e0a43f98e9feb8f284d68e9c79273647d3fadb7477532259de96840cfc67d2ebf3 + "@zksync/contracts": "github:matter-labs/era-contracts#446d391d34bdb48255d5f8fef8a8248925fc98b9" + semver: "npm:^7.7.1" + checksum: 10/df6259b00fbed15cbe4723ce4ff93e2d2d49dc2463b5851f6ffc7b4c07ee3a3d517fb5b3a44adae06cf9bd7aa0cd26185b4fe0ee4a0ad16a9c5f9440b73ec9ac languageName: node linkType: hard @@ -2006,13 +1971,13 @@ __metadata: languageName: node linkType: hard -"@changesets/apply-release-plan@npm:^7.0.8": - version: 7.0.10 - resolution: "@changesets/apply-release-plan@npm:7.0.10" +"@changesets/apply-release-plan@npm:^7.0.10": + version: 7.0.12 + resolution: "@changesets/apply-release-plan@npm:7.0.12" dependencies: "@changesets/config": "npm:^3.1.1" "@changesets/get-version-range-type": "npm:^0.4.0" - "@changesets/git": "npm:^3.0.2" + "@changesets/git": "npm:^3.0.4" "@changesets/should-skip-package": "npm:^0.1.2" "@changesets/types": "npm:^6.1.0" "@manypkg/get-packages": "npm:^1.1.3" @@ -2023,11 +1988,11 @@ __metadata: prettier: "npm:^2.7.1" resolve-from: "npm:^5.0.0" semver: "npm:^7.5.3" - checksum: 10/8d37aa245dd0879fbb90a65cbeafd6b32b0076dcec5f49a6663812cb58eec6e7e9195c16e2050a34e0400741d573d85fc4a807d1ae1f427fb88df914f9a4e182 + checksum: 10/3ce05caa73b7b96a8a6be943507591925c44b22f209da001fb9d83df1d7a4569659e889373f5f7a208a121b3cf7bc17788969b8849bddaf13c27d6720e4e1c47 languageName: node linkType: hard -"@changesets/assemble-release-plan@npm:^6.0.5, @changesets/assemble-release-plan@npm:^6.0.6": +"@changesets/assemble-release-plan@npm:^6.0.6": version: 6.0.6 resolution: "@changesets/assemble-release-plan@npm:6.0.6" dependencies: @@ -2041,44 +2006,47 @@ __metadata: languageName: node linkType: hard -"@changesets/changelog-git@npm:^0.2.0": - version: 0.2.1 - resolution: "@changesets/changelog-git@npm:0.2.1" +"@changesets/assemble-release-plan@npm:^6.0.9": + version: 6.0.9 + resolution: "@changesets/assemble-release-plan@npm:6.0.9" dependencies: + "@changesets/errors": "npm:^0.2.0" + "@changesets/get-dependents-graph": "npm:^2.1.3" + "@changesets/should-skip-package": "npm:^0.1.2" "@changesets/types": "npm:^6.1.0" - checksum: 10/c22f3c0baf50c102a6890046351ee42f65ff6d58747ba4f75e5e40da1ed5fbcfd0dc2d11cdfb86acbb3262e58acb93f096c798827cac570c1e22e8f32f58a30f + "@manypkg/get-packages": "npm:^1.1.3" + semver: "npm:^7.5.3" + checksum: 10/f84656eabb700ed77f97751b282e1701636ed45a44b443abd9af0291870495cc046fee301478010f39a1dc455799065ae007b9d7d2bb5ae8b793b65bbb8e052a languageName: node linkType: hard -"@changesets/changelog-github@npm:^0.5.0": - version: 0.5.1 - resolution: "@changesets/changelog-github@npm:0.5.1" +"@changesets/changelog-git@npm:^0.2.1": + version: 0.2.1 + resolution: "@changesets/changelog-git@npm:0.2.1" dependencies: - "@changesets/get-github-info": "npm:^0.6.0" "@changesets/types": "npm:^6.1.0" - dotenv: "npm:^8.1.0" - checksum: 10/1284e7dc067652edfa14792196e6036849455d121afabe63e8d1a7dc0e8fb0310edb58d1130f2a5944819ae4011eeecc7e0c44c1cda43e6a581a3add187c3447 + checksum: 10/c22f3c0baf50c102a6890046351ee42f65ff6d58747ba4f75e5e40da1ed5fbcfd0dc2d11cdfb86acbb3262e58acb93f096c798827cac570c1e22e8f32f58a30f languageName: node linkType: hard -"@changesets/cli@npm:~2.27.8": - version: 2.27.12 - resolution: "@changesets/cli@npm:2.27.12" +"@changesets/cli@npm:~2.28.1": + version: 2.28.1 + resolution: "@changesets/cli@npm:2.28.1" dependencies: - "@changesets/apply-release-plan": "npm:^7.0.8" - "@changesets/assemble-release-plan": "npm:^6.0.5" - "@changesets/changelog-git": "npm:^0.2.0" - "@changesets/config": "npm:^3.0.5" + "@changesets/apply-release-plan": "npm:^7.0.10" + "@changesets/assemble-release-plan": "npm:^6.0.6" + "@changesets/changelog-git": "npm:^0.2.1" + "@changesets/config": "npm:^3.1.1" "@changesets/errors": "npm:^0.2.0" - "@changesets/get-dependents-graph": "npm:^2.1.2" - "@changesets/get-release-plan": "npm:^4.0.6" + "@changesets/get-dependents-graph": "npm:^2.1.3" + "@changesets/get-release-plan": "npm:^4.0.8" "@changesets/git": "npm:^3.0.2" "@changesets/logger": "npm:^0.1.1" - "@changesets/pre": "npm:^2.0.1" - "@changesets/read": "npm:^0.6.2" - "@changesets/should-skip-package": "npm:^0.1.1" - "@changesets/types": "npm:^6.0.0" - "@changesets/write": "npm:^0.3.2" + "@changesets/pre": "npm:^2.0.2" + "@changesets/read": "npm:^0.6.3" + "@changesets/should-skip-package": "npm:^0.1.2" + "@changesets/types": "npm:^6.1.0" + "@changesets/write": "npm:^0.4.0" "@manypkg/get-packages": "npm:^1.1.3" ansi-colors: "npm:^4.1.3" ci-info: "npm:^3.7.0" @@ -2095,11 +2063,11 @@ __metadata: term-size: "npm:^2.1.0" bin: changeset: bin.js - checksum: 10/06618abc60ddd9bb82d0380ee6bdea926cce8ebd76e18eb38487fa2501ee1386ffaf55042c8d052d783bcfd2669c51f3eef8b0b0cfc7624486bcec42ac0da9da + checksum: 10/c2cb4063bfd02147970bd629565d05d7e13b9649446997ea5c17e250ef290a1b093f2a2cfaf1e6856597aa435499758f9d6d98bfb24035533376a9d2cc7f37f2 languageName: node linkType: hard -"@changesets/config@npm:^3.0.5, @changesets/config@npm:^3.1.1": +"@changesets/config@npm:^3.1.1": version: 3.1.1 resolution: "@changesets/config@npm:3.1.1" dependencies: @@ -2123,7 +2091,7 @@ __metadata: languageName: node linkType: hard -"@changesets/get-dependents-graph@npm:^2.1.2, @changesets/get-dependents-graph@npm:^2.1.3": +"@changesets/get-dependents-graph@npm:^2.1.3": version: 2.1.3 resolution: "@changesets/get-dependents-graph@npm:2.1.3" dependencies: @@ -2145,17 +2113,17 @@ __metadata: languageName: node linkType: hard -"@changesets/get-release-plan@npm:^4.0.6": - version: 4.0.8 - resolution: "@changesets/get-release-plan@npm:4.0.8" +"@changesets/get-release-plan@npm:^4.0.8": + version: 4.0.13 + resolution: "@changesets/get-release-plan@npm:4.0.13" dependencies: - "@changesets/assemble-release-plan": "npm:^6.0.6" + "@changesets/assemble-release-plan": "npm:^6.0.9" "@changesets/config": "npm:^3.1.1" "@changesets/pre": "npm:^2.0.2" - "@changesets/read": "npm:^0.6.3" + "@changesets/read": "npm:^0.6.5" "@changesets/types": "npm:^6.1.0" "@manypkg/get-packages": "npm:^1.1.3" - checksum: 10/9d61bc348d99cede703b7efa66aebf2bb8fcf4868491bd311aec3a36c75c966fde45582573d4f03a2c31931dfd3cf318e359b9c86c1af3b41eecabf5da50e0a7 + checksum: 10/9983fae5a68012c4c418ddd62f2fb3d325363f21160252ff7b868503a1a2effb8fdd32e4a0289b72653afc3605ce19d163ff69205c942a0004efb571a5f78fd0 languageName: node linkType: hard @@ -2179,6 +2147,19 @@ __metadata: languageName: node linkType: hard +"@changesets/git@npm:^3.0.4": + version: 3.0.4 + resolution: "@changesets/git@npm:3.0.4" + dependencies: + "@changesets/errors": "npm:^0.2.0" + "@manypkg/get-packages": "npm:^1.1.3" + is-subdir: "npm:^1.1.1" + micromatch: "npm:^4.0.8" + spawndamnit: "npm:^3.0.1" + checksum: 10/4f5a1f3354ec39d530df78b198eaaf2a8ef6cca873dd18efb8706aae09cab04e0d985abd236288644fac5d10cc5cb6ba2538c3e0be023c4d80790ff841f39fa6 + languageName: node + linkType: hard + "@changesets/logger@npm:^0.1.1": version: 0.1.1 resolution: "@changesets/logger@npm:0.1.1" @@ -2198,7 +2179,7 @@ __metadata: languageName: node linkType: hard -"@changesets/pre@npm:^2.0.1, @changesets/pre@npm:^2.0.2": +"@changesets/pre@npm:^2.0.2": version: 2.0.2 resolution: "@changesets/pre@npm:2.0.2" dependencies: @@ -2210,7 +2191,7 @@ __metadata: languageName: node linkType: hard -"@changesets/read@npm:^0.6.2, @changesets/read@npm:^0.6.3": +"@changesets/read@npm:^0.6.3": version: 0.6.3 resolution: "@changesets/read@npm:0.6.3" dependencies: @@ -2225,7 +2206,22 @@ __metadata: languageName: node linkType: hard -"@changesets/should-skip-package@npm:^0.1.1, @changesets/should-skip-package@npm:^0.1.2": +"@changesets/read@npm:^0.6.5": + version: 0.6.5 + resolution: "@changesets/read@npm:0.6.5" + dependencies: + "@changesets/git": "npm:^3.0.4" + "@changesets/logger": "npm:^0.1.1" + "@changesets/parse": "npm:^0.4.1" + "@changesets/types": "npm:^6.1.0" + fs-extra: "npm:^7.0.1" + p-filter: "npm:^2.1.0" + picocolors: "npm:^1.1.0" + checksum: 10/fec0ac28801e0560fae0eb1d21250dd2a48aaff67bddd1b446a960afd761690d5873dca6eff369d43763bec61f1023d38a38876d5824e316e6de622dc52a24f3 + languageName: node + linkType: hard + +"@changesets/should-skip-package@npm:^0.1.2": version: 0.1.2 resolution: "@changesets/should-skip-package@npm:0.1.2" dependencies: @@ -2242,22 +2238,22 @@ __metadata: languageName: node linkType: hard -"@changesets/types@npm:^6.0.0, @changesets/types@npm:^6.1.0": +"@changesets/types@npm:^6.1.0": version: 6.1.0 resolution: "@changesets/types@npm:6.1.0" checksum: 10/2dcd00712cb85d0c53afdd8d0e856b4bf9c0ce8dc36c838c918d44799aacd9ba8659b9ff610ff92b94fc03c8fd2b52c5b05418fcf8a1bd138cd9182414ede373 languageName: node linkType: hard -"@changesets/write@npm:^0.3.2": - version: 0.3.2 - resolution: "@changesets/write@npm:0.3.2" +"@changesets/write@npm:^0.4.0": + version: 0.4.0 + resolution: "@changesets/write@npm:0.4.0" dependencies: - "@changesets/types": "npm:^6.0.0" + "@changesets/types": "npm:^6.1.0" fs-extra: "npm:^7.0.1" - human-id: "npm:^1.0.2" + human-id: "npm:^4.1.1" prettier: "npm:^2.7.1" - checksum: 10/c16b0a731fa43ae0028fd1f956c7b080030c42ff763f8dac74da8b178a4ea65632831c30550b784286277bdc75a3c44dda46aad8db97f43bb1eb4d61922152aa + checksum: 10/bcea8431a09e282bdf66adbd8411d5d3cc19b4a2df519a42586c912b23a7b3ef18d1d0765e2d1a27ff175e2dfc9ef4c2df95cfa920dd4dd2972aaaf662afc6b9 languageName: node linkType: hard @@ -4956,7 +4952,7 @@ __metadata: "@kleros/escrow-v2-eslint-config": "workspace:^" "@kleros/escrow-v2-prettier-config": "workspace:^" "@kleros/escrow-v2-tsconfig": "workspace:^" - "@kleros/kleros-v2-contracts": "npm:^0.9.3" + "@kleros/kleros-v2-contracts": "npm:^0.10.0" "@logtail/pino": "npm:^0.4.0" "@nomicfoundation/hardhat-chai-matchers": "npm:^2.0.8" "@nomicfoundation/hardhat-ethers": "npm:^3.0.8" @@ -5050,7 +5046,7 @@ __metadata: "@graphql-codegen/cli": "npm:^4.0.1" "@graphql-codegen/client-preset": "npm:^4.6.2" "@kleros/kleros-app": "npm:^2.1.0" - "@kleros/kleros-v2-contracts": "npm:^0.9.3" + "@kleros/kleros-v2-contracts": "npm:^0.10.0" "@kleros/ui-components-library": "npm:^2.19.0" "@reown/appkit": "npm:^1.6.6" "@reown/appkit-adapter-wagmi": "npm:^1.6.6" @@ -5122,15 +5118,17 @@ __metadata: languageName: node linkType: hard -"@kleros/kleros-v2-contracts@npm:^0.9.3": - version: 0.9.3 - resolution: "@kleros/kleros-v2-contracts@npm:0.9.3" +"@kleros/kleros-v2-contracts@npm:^0.10.0": + version: 0.10.0 + resolution: "@kleros/kleros-v2-contracts@npm:0.10.0" dependencies: - "@chainlink/contracts": "npm:^1.3.0" + "@chainlink/contracts": "npm:^1.4.0" "@kleros/vea-contracts": "npm:^0.6.0" - "@openzeppelin/contracts": "npm:^5.2.0" + "@openzeppelin/contracts": "npm:^5.4.0" + "@shutter-network/shutter-sdk": "npm:^0.0.2" + isomorphic-fetch: "npm:^3.0.0" viem: "npm:^2.24.1" - checksum: 10/39862f09fc516f24e1ec2fc3bdde22aa83f58bada40c58e83ca15c8422b713cb8eac666673c67daf4873f4ca3d7c80ca3b7448d56936165847298b93ca2a9478 + checksum: 10/a0937144cbd4e39fb58fb4ef6e9cac6b4bb56284fc2acf4f8ebdec26e396cf0eeec9e90d6cf588e78e4c35aedccac1a4cb7077d09b615326451c24fa67f3f294 languageName: node linkType: hard @@ -5764,6 +5762,13 @@ __metadata: languageName: node linkType: hard +"@noble/ciphers@npm:^1.3.0": + version: 1.3.0 + resolution: "@noble/ciphers@npm:1.3.0" + checksum: 10/051660051e3e9e2ca5fb9dece2885532b56b7e62946f89afa7284a0fb8bc02e2bd1c06554dba68162ff42d295b54026456084198610f63c296873b2f1cd7a586 + languageName: node + linkType: hard + "@noble/curves@npm:1.1.0, @noble/curves@npm:~1.1.0": version: 1.1.0 resolution: "@noble/curves@npm:1.1.0" @@ -5818,6 +5823,15 @@ __metadata: languageName: node linkType: hard +"@noble/curves@npm:1.9.2": + version: 1.9.2 + resolution: "@noble/curves@npm:1.9.2" + dependencies: + "@noble/hashes": "npm:1.8.0" + checksum: 10/f60f00ad86296054566b67be08fd659999bb64b692bfbf11dbe3be1f422ad4d826bf5ebb2015ce2e246538eab2b677707e0a46ffa8323a6fae7a9a30ec1fe318 + languageName: node + linkType: hard + "@noble/curves@npm:^1.6.0, @noble/curves@npm:~1.7.0": version: 1.7.0 resolution: "@noble/curves@npm:1.7.0" @@ -5827,6 +5841,15 @@ __metadata: languageName: node linkType: hard +"@noble/curves@npm:^1.9.1, @noble/curves@npm:~1.9.0": + version: 1.9.4 + resolution: "@noble/curves@npm:1.9.4" + dependencies: + "@noble/hashes": "npm:1.8.0" + checksum: 10/e8e9a05f27dc79e8f67001ddf81b69c527e3879085841647a07e150fc1c28fd5b576cce1f411daaa0cae40f8c65b2fd6c457f4165b2c4c9fbe327173ba1d8845 + languageName: node + linkType: hard + "@noble/hashes@npm:1.2.0, @noble/hashes@npm:~1.2.0": version: 1.2.0 resolution: "@noble/hashes@npm:1.2.0" @@ -5876,6 +5899,13 @@ __metadata: languageName: node linkType: hard +"@noble/hashes@npm:1.8.0, @noble/hashes@npm:^1.8.0, @noble/hashes@npm:~1.8.0": + version: 1.8.0 + resolution: "@noble/hashes@npm:1.8.0" + checksum: 10/474b7f56bc6fb2d5b3a42132561e221b0ea4f91e590f4655312ca13667840896b34195e2b53b7f097ec080a1fdd3b58d902c2a8d0fbdf51d2e238b53808a177e + languageName: node + linkType: hard + "@noble/hashes@npm:^1.3.1, @noble/hashes@npm:~1.3.0, @noble/hashes@npm:~1.3.1": version: 1.3.3 resolution: "@noble/hashes@npm:1.3.3" @@ -6018,15 +6048,6 @@ __metadata: languageName: node linkType: hard -"@nomicfoundation/slang@npm:^0.18.3": - version: 0.18.3 - resolution: "@nomicfoundation/slang@npm:0.18.3" - dependencies: - "@bytecodealliance/preview2-shim": "npm:0.17.0" - checksum: 10/1dcf687e4719844bffc688d13d15c0db3218ab05983d6b53777a3172c7df157c105171e802fe7812d9fd2bdb4dcd8d7287367c851eed4dfd76621e799c14574f - languageName: node - linkType: hard - "@nomicfoundation/solidity-analyzer-darwin-arm64@npm:0.1.1": version: 0.1.1 resolution: "@nomicfoundation/solidity-analyzer-darwin-arm64@npm:0.1.1" @@ -6269,13 +6290,6 @@ __metadata: languageName: node linkType: hard -"@openzeppelin/contracts-upgradeable@npm:4.5.2": - version: 4.5.2 - resolution: "@openzeppelin/contracts-upgradeable@npm:4.5.2" - checksum: 10/5e246da7a44bb982a312ebf79978735712140692d46273566e490159b98b9041ca72cc08c3d05172137a389be4caad5afc001480bc5557f3d47162f4626e3723 - languageName: node - linkType: hard - "@openzeppelin/contracts-upgradeable@npm:4.7.3": version: 4.7.3 resolution: "@openzeppelin/contracts-upgradeable@npm:4.7.3" @@ -6283,24 +6297,10 @@ __metadata: languageName: node linkType: hard -"@openzeppelin/contracts-upgradeable@npm:4.8.3": - version: 4.8.3 - resolution: "@openzeppelin/contracts-upgradeable@npm:4.8.3" - checksum: 10/1ff70629f509221ef948da6de582fd19a6cf7deea884f0c2de1347ca5eb1f3910099f92fcaf1a70fcae982d8f95b58f48548d833e6ad708e5d7afbae1556fae8 - languageName: node - linkType: hard - -"@openzeppelin/contracts-upgradeable@npm:4.9.3": - version: 4.9.3 - resolution: "@openzeppelin/contracts-upgradeable@npm:4.9.3" - checksum: 10/d8fd6fd9d2271fbdd3958c20769b72a241687883ecd3bea05a3969568cdcabdee9d53c21ac776a651c397507d9c22d8db0a4fb970d27bdab918979fae7285a2f - languageName: node - linkType: hard - -"@openzeppelin/contracts@npm:4.5.0": - version: 4.5.0 - resolution: "@openzeppelin/contracts@npm:4.5.0" - checksum: 10/8bfa1733732420331728cedd7f1f5f4e4ae0700b32c9e5def19b2d42dbb0b246709e8e22abd457e8269d743012ff2aed4e3f100a942f45d9507cb78d5dbd435b +"@openzeppelin/contracts-upgradeable@npm:4.9.6": + version: 4.9.6 + resolution: "@openzeppelin/contracts-upgradeable@npm:4.9.6" + checksum: 10/af9057147f13b6f0e13ca69581777f615f2cce8c6c274ec00fbea906a9095cd9ca1fb70e2c1282122a9f522fd639641c180bf1ad79bb2722494aac5ae9e565bc languageName: node linkType: hard @@ -6311,24 +6311,10 @@ __metadata: languageName: node linkType: hard -"@openzeppelin/contracts@npm:4.8.3": - version: 4.8.3 - resolution: "@openzeppelin/contracts@npm:4.8.3" - checksum: 10/276481d76afdc71690bd4204cdd47e6add30d183e20df57c76e5ffc481c783ca756842f3b0ac7e3e6336217dcde448cef8279fafae1176ac436ad86594c4bdc2 - languageName: node - linkType: hard - -"@openzeppelin/contracts@npm:4.9.3": - version: 4.9.3 - resolution: "@openzeppelin/contracts@npm:4.9.3" - checksum: 10/ce0a16a56a39b62d72370ac702bce1917096492442ff05de88521beda2c3f3935b93ee2b9a184614dd543a6181f2f0be10243f5a629be87aab284ade68c18320 - languageName: node - linkType: hard - -"@openzeppelin/contracts@npm:^5.2.0": - version: 5.2.0 - resolution: "@openzeppelin/contracts@npm:5.2.0" - checksum: 10/d77e1bdfca6fa1c40b5a32bb92220ec633ef86cc0bf43a011ad218c26c9e763c70ace3fc1e148a0462394a3aed8c5d7445935ebfeb146ba1454abec66625e420 +"@openzeppelin/contracts@npm:4.9.6": + version: 4.9.6 + resolution: "@openzeppelin/contracts@npm:4.9.6" + checksum: 10/71f45ad42e68c0559be4ba502115462a01c76fc805c08d3005c10b5550a093f1a2b00b2d7e9d6d1f331e147c50fd4ad832f71c4470ec5b34f5a2d0751cd19a47 languageName: node linkType: hard @@ -6339,23 +6325,10 @@ __metadata: languageName: node linkType: hard -"@openzeppelin/upgrades-core@npm:^1.24.1": - version: 1.42.2 - resolution: "@openzeppelin/upgrades-core@npm:1.42.2" - dependencies: - "@nomicfoundation/slang": "npm:^0.18.3" - cbor: "npm:^10.0.0" - chalk: "npm:^4.1.0" - compare-versions: "npm:^6.0.0" - debug: "npm:^4.1.1" - ethereumjs-util: "npm:^7.0.3" - minimatch: "npm:^9.0.5" - minimist: "npm:^1.2.7" - proper-lockfile: "npm:^4.1.1" - solidity-ast: "npm:^0.4.51" - bin: - openzeppelin-upgrades-core: dist/cli/cli.js - checksum: 10/7000c7cf6822eab2b8a927acc1f09b769004667644e389ae582cd4f87f74433cdd3bc80477f95990d40bb60c15b85e61e5ad4cd47e0e7e70c4e5cbef6cbad10c +"@openzeppelin/contracts@npm:^5.4.0": + version: 5.4.0 + resolution: "@openzeppelin/contracts@npm:5.4.0" + checksum: 10/4f7f926ebd98279ba8223cae5d2cd38e0806e60e3e3a615c9d739ffab870ffab7a1e85f47092faa123c0f26d1699ca15252adea8bcdcaf360b21781acc93b218 languageName: node linkType: hard @@ -7195,6 +7168,13 @@ __metadata: languageName: node linkType: hard +"@scure/base@npm:~1.2.5": + version: 1.2.6 + resolution: "@scure/base@npm:1.2.6" + checksum: 10/c1a7bd5e0b0c8f94c36fbc220f4a67cc832b00e2d2065c7d8a404ed81ab1c94c5443def6d361a70fc382db3496e9487fb9941728f0584782b274c18a4bed4187 + languageName: node + linkType: hard + "@scure/bip32@npm:1.1.5": version: 1.1.5 resolution: "@scure/bip32@npm:1.1.5" @@ -7239,6 +7219,17 @@ __metadata: languageName: node linkType: hard +"@scure/bip32@npm:1.7.0, @scure/bip32@npm:^1.7.0": + version: 1.7.0 + resolution: "@scure/bip32@npm:1.7.0" + dependencies: + "@noble/curves": "npm:~1.9.0" + "@noble/hashes": "npm:~1.8.0" + "@scure/base": "npm:~1.2.5" + checksum: 10/f90e0c23ab6a31a164856ae9cb9a8cae2886df608c74a6c0c4875095b017e30ffd92f28f73b8c52890d9a89fca86d19f6d60bb1ea7cad64c7987f92ae83509ad + languageName: node + linkType: hard + "@scure/bip32@npm:^1.5.0": version: 1.6.0 resolution: "@scure/bip32@npm:1.6.0" @@ -7290,6 +7281,16 @@ __metadata: languageName: node linkType: hard +"@scure/bip39@npm:1.6.0, @scure/bip39@npm:^1.6.0": + version: 1.6.0 + resolution: "@scure/bip39@npm:1.6.0" + dependencies: + "@noble/hashes": "npm:~1.8.0" + "@scure/base": "npm:~1.2.5" + checksum: 10/63e60c40fa1bda2c1b50351546fee6d7b0947cc814aa7a4209dcedd3693b5053302c8fca28292f5f50735e11c613265359acdc019127393dbab17e53489fc449 + languageName: node + linkType: hard + "@scure/bip39@npm:^1.4.0": version: 1.5.0 resolution: "@scure/bip39@npm:1.5.0" @@ -7492,6 +7493,18 @@ __metadata: languageName: node linkType: hard +"@shutter-network/shutter-sdk@npm:^0.0.2": + version: 0.0.2 + resolution: "@shutter-network/shutter-sdk@npm:0.0.2" + dependencies: + browser-or-node: "npm:^3.0.0" + buffer: "npm:^6.0.3" + lodash: "npm:^4.17.21" + viem: "npm:^2.23.2" + checksum: 10/da53a9cf757be3204fa0e806e6a39e9dee6f6141471c9220c82f5a8f461615b565d30516880eaaa5d31308345839e7f8e9b5534fd9f0eb0abc243ff4c774becd + languageName: node + linkType: hard + "@sinclair/typebox@npm:^0.24.1": version: 0.24.51 resolution: "@sinclair/typebox@npm:0.24.51" @@ -9924,7 +9937,7 @@ __metadata: languageName: node linkType: hard -"@zksync/contracts@git+https://github.com/matter-labs/era-contracts.git#446d391d34bdb48255d5f8fef8a8248925fc98b9": +"@zksync/contracts@github:matter-labs/era-contracts#446d391d34bdb48255d5f8fef8a8248925fc98b9": version: 0.1.0 resolution: "@zksync/contracts@https://github.com/matter-labs/era-contracts.git#commit=446d391d34bdb48255d5f8fef8a8248925fc98b9" checksum: 10/982b27c109e55a332f6690e164230a033f3c8292dc816b46798704410796caee5b7b3336d9fd238b5b2aedc7a8ffb54ee294e948d11cfb22e925a4c17392e5ab @@ -11382,6 +11395,13 @@ __metadata: languageName: node linkType: hard +"browser-or-node@npm:^3.0.0": + version: 3.0.0 + resolution: "browser-or-node@npm:3.0.0" + checksum: 10/51d74cc5d0139da3d37e83ff3906fcca20d02c42aa8b81a48d9ea01806f36df1a4b55006670071b1d7423967777275920054ec8b723410534b580b0232c5093d + languageName: node + linkType: hard + "browser-process-hrtime@npm:^1.0.0": version: 1.0.0 resolution: "browser-process-hrtime@npm:1.0.0" @@ -11852,15 +11872,6 @@ __metadata: languageName: node linkType: hard -"cbor@npm:^10.0.0": - version: 10.0.3 - resolution: "cbor@npm:10.0.3" - dependencies: - nofilter: "npm:^3.0.2" - checksum: 10/ff33c3404c3acc8afc448163a7b32eea39f4f99d641ac496352a6830256617a0b1d49b2862746b6b150e8931b6f6da10572d78c28af3a64b6836881c33c5d942 - languageName: node - linkType: hard - "cborg@npm:^4.0.0": version: 4.2.8 resolution: "cborg@npm:4.2.8" @@ -12558,13 +12569,6 @@ __metadata: languageName: node linkType: hard -"compare-versions@npm:^6.0.0": - version: 6.1.1 - resolution: "compare-versions@npm:6.1.1" - checksum: 10/9325c0fadfba81afa0ec17e6fc2ef823ba785c693089698b8d9374e5460509f1916a88591644d4cb4045c9a58e47fafbcc0724fe8bf446d2a875a3d6eeddf165 - languageName: node - linkType: hard - "compressible@npm:~2.0.16": version: 2.0.18 resolution: "compressible@npm:2.0.18" @@ -14303,13 +14307,6 @@ __metadata: languageName: node linkType: hard -"dotenv@npm:^8.1.0": - version: 8.6.0 - resolution: "dotenv@npm:8.6.0" - checksum: 10/31d7b5c010cebb80046ba6853d703f9573369b00b15129536494f04b0af4ea0060ce8646e3af58b455af2f6f1237879dd261a5831656410ec92561ae1ea44508 - languageName: node - linkType: hard - "dset@npm:^3.1.2": version: 3.1.3 resolution: "dset@npm:3.1.3" @@ -15743,7 +15740,7 @@ __metadata: languageName: node linkType: hard -"ethereumjs-util@npm:^7.0.3, ethereumjs-util@npm:^7.1.5": +"ethereumjs-util@npm:^7.1.5": version: 7.1.5 resolution: "ethereumjs-util@npm:7.1.5" dependencies: @@ -18006,10 +18003,12 @@ __metadata: languageName: node linkType: hard -"human-id@npm:^1.0.2": - version: 1.0.2 - resolution: "human-id@npm:1.0.2" - checksum: 10/16b116ef68c3fc3f65c90b32a338abd0f9ee656a6257baa92c4d7e1154c66469bb6bd4ee840018c35e972aa817f5ae3f0cbabffb78f2ac90aaf02d88a299a371 +"human-id@npm:^4.1.1": + version: 4.1.1 + resolution: "human-id@npm:4.1.1" + bin: + human-id: dist/cli.js + checksum: 10/84fef1edd470fc155a34161107beed8baf77bafd20bf515c3fadfbce3690ecc9aa0bacf3fcf4cf9add3c274772ead3ef64aa6531374538ffebe8129fccfb0015 languageName: node linkType: hard @@ -18955,6 +18954,16 @@ __metadata: languageName: node linkType: hard +"isomorphic-fetch@npm:^3.0.0": + version: 3.0.0 + resolution: "isomorphic-fetch@npm:3.0.0" + dependencies: + node-fetch: "npm:^2.6.1" + whatwg-fetch: "npm:^3.4.1" + checksum: 10/568fe0307528c63405c44dd3873b7b6c96c0d19ff795cb15846e728b6823bdbc68cc8c97ac23324509661316f12f551e43dac2929bc7030b8bc4d6aa1158b857 + languageName: node + linkType: hard + "isomorphic-timers-promises@npm:^1.0.1": version: 1.0.1 resolution: "isomorphic-timers-promises@npm:1.0.1" @@ -18998,6 +19007,15 @@ __metadata: languageName: node linkType: hard +"isows@npm:1.0.7": + version: 1.0.7 + resolution: "isows@npm:1.0.7" + peerDependencies: + ws: "*" + checksum: 10/044b949b369872882af07b60b613b5801ae01b01a23b5b72b78af80c8103bbeed38352c3e8ceff13a7834bc91fd2eb41cf91ec01d59a041d8705680e6b0ec546 + languageName: node + linkType: hard + "istanbul-lib-coverage@npm:^3.0.0, istanbul-lib-coverage@npm:^3.2.0": version: 3.2.2 resolution: "istanbul-lib-coverage@npm:3.2.2" @@ -21752,7 +21770,7 @@ __metadata: languageName: node linkType: hard -"minimist@npm:^1.2.0, minimist@npm:^1.2.5, minimist@npm:^1.2.6, minimist@npm:^1.2.7": +"minimist@npm:^1.2.0, minimist@npm:^1.2.5, minimist@npm:^1.2.6": version: 1.2.8 resolution: "minimist@npm:1.2.8" checksum: 10/908491b6cc15a6c440ba5b22780a0ba89b9810e1aea684e253e43c4e3b8d56ec1dcdd7ea96dde119c29df59c936cde16062159eae4225c691e19c70b432b6e6f @@ -22350,13 +22368,6 @@ __metadata: languageName: node linkType: hard -"nofilter@npm:^3.0.2": - version: 3.1.0 - resolution: "nofilter@npm:3.1.0" - checksum: 10/f63d87231dfda4b783db17d75b15aac948f78e65f4f1043096ef441147f6667ff74cd4b3f57ada5dbe240be282d3e9838558ac863a66cb04ef25fff7b2b4be4e - languageName: node - linkType: hard - "nopt@npm:3.x": version: 3.0.6 resolution: "nopt@npm:3.0.6" @@ -22912,6 +22923,27 @@ __metadata: languageName: node linkType: hard +"ox@npm:0.8.1": + version: 0.8.1 + resolution: "ox@npm:0.8.1" + dependencies: + "@adraffy/ens-normalize": "npm:^1.11.0" + "@noble/ciphers": "npm:^1.3.0" + "@noble/curves": "npm:^1.9.1" + "@noble/hashes": "npm:^1.8.0" + "@scure/bip32": "npm:^1.7.0" + "@scure/bip39": "npm:^1.6.0" + abitype: "npm:^1.0.8" + eventemitter3: "npm:5.0.1" + peerDependencies: + typescript: ">=5.4.0" + peerDependenciesMeta: + typescript: + optional: true + checksum: 10/a3c967e5b30792d89e7ecbdf976c00c625738e96263e1f0a95ad43c27b57ac18f21357eb7a651ce3c0ff0dc54b3ed071516c9804bc48fa2134262a5066b62fcc + languageName: node + linkType: hard + "p-cancelable@npm:^3.0.0": version: 3.0.0 resolution: "p-cancelable@npm:3.0.0" @@ -24745,17 +24777,6 @@ __metadata: languageName: node linkType: hard -"proper-lockfile@npm:^4.1.1": - version: 4.1.2 - resolution: "proper-lockfile@npm:4.1.2" - dependencies: - graceful-fs: "npm:^4.2.4" - retry: "npm:^0.12.0" - signal-exit: "npm:^3.0.2" - checksum: 10/000a4875f543f591872b36ca94531af8a6463ddb0174f41c0b004d19e231d7445268b422ff1ea595e43d238655c702250cd3d27f408e7b9d97b56f1533ba26bf - languageName: node - linkType: hard - "property-information@npm:^6.0.0": version: 6.4.0 resolution: "property-information@npm:6.4.0" @@ -26716,6 +26737,15 @@ __metadata: languageName: node linkType: hard +"semver@npm:^7.7.1": + version: 7.7.2 + resolution: "semver@npm:7.7.2" + bin: + semver: bin/semver.js + checksum: 10/7a24cffcaa13f53c09ce55e05efe25cd41328730b2308678624f8b9f5fc3093fc4d189f47950f0b811ff8f3c3039c24a2c36717ba7961615c682045bf03e1dda + languageName: node + linkType: hard + "send@npm:0.18.0": version: 0.18.0 resolution: "send@npm:0.18.0" @@ -27203,6 +27233,13 @@ __metadata: languageName: node linkType: hard +"solady@npm:0.0.182": + version: 0.0.182 + resolution: "solady@npm:0.0.182" + checksum: 10/3bc02c37da3e791b366ecbfa1b28bf204926c206f3c36da59cc11c16b97775fa62720022a5b3b7849b4a5efda33bcc829a0a24a411782232e247c85bc945c971 + languageName: node + linkType: hard + "solc@npm:0.8.26": version: 0.8.26 resolution: "solc@npm:0.8.26" @@ -27252,13 +27289,6 @@ __metadata: languageName: node linkType: hard -"solidity-ast@npm:^0.4.51": - version: 0.4.60 - resolution: "solidity-ast@npm:0.4.60" - checksum: 10/1811d4f5c3b767875819127a9eed125700840124d4d958a09f77cca33f224b4d075567344e366d12569fc6a1974798a30359fb817abf7cbaf320fbd7891e95bd - languageName: node - linkType: hard - "solidity-coverage@npm:^0.8.14": version: 0.8.14 resolution: "solidity-coverage@npm:0.8.14" @@ -29873,6 +29903,27 @@ __metadata: languageName: node linkType: hard +"viem@npm:^2.23.2": + version: 2.32.1 + resolution: "viem@npm:2.32.1" + dependencies: + "@noble/curves": "npm:1.9.2" + "@noble/hashes": "npm:1.8.0" + "@scure/bip32": "npm:1.7.0" + "@scure/bip39": "npm:1.6.0" + abitype: "npm:1.0.8" + isows: "npm:1.0.7" + ox: "npm:0.8.1" + ws: "npm:8.18.2" + peerDependencies: + typescript: ">=5.0.4" + peerDependenciesMeta: + typescript: + optional: true + checksum: 10/890c82d32c8db6717c65d9a37daf6223bc9313ceb1cc22b19b8fc49ded18198bf060fd2fd27676a5b1cdbf1ea36cb9b4a44b75a608218251d54b41d189a7022c + languageName: node + linkType: hard + "viem@npm:^2.24.1": version: 2.26.3 resolution: "viem@npm:2.26.3" @@ -30512,7 +30563,7 @@ __metadata: languageName: node linkType: hard -"whatwg-fetch@npm:^3.6.2": +"whatwg-fetch@npm:^3.4.1, whatwg-fetch@npm:^3.6.2": version: 3.6.20 resolution: "whatwg-fetch@npm:3.6.20" checksum: 10/2b4ed92acd6a7ad4f626a6cb18b14ec982bbcaf1093e6fe903b131a9c6decd14d7f9c9ca3532663c2759d1bdf01d004c77a0adfb2716a5105465c20755a8c57c @@ -31031,6 +31082,21 @@ __metadata: languageName: node linkType: hard +"ws@npm:8.18.2": + version: 8.18.2 + resolution: "ws@npm:8.18.2" + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ">=5.0.2" + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + checksum: 10/018e04ec95561d88248d53a2eaf094b4ae131e9b062f2679e6e8a62f04649bc543448f1e038125225ac6bbb25f54c1e65d7a2cc9dbc1e28b43e5e6b7162ad88e + languageName: node + linkType: hard + "ws@npm:^7.4.6, ws@npm:^7.5.1": version: 7.5.9 resolution: "ws@npm:7.5.9" From 0ef0d8ba1126ddb035aad076348f76470e584047 Mon Sep 17 00:00:00 2001 From: unknownunknown1 Date: Wed, 23 Jul 2025 19:46:16 +1000 Subject: [PATCH 06/13] refactor(Escrow): use inheritance for custom buyer --- contracts/src/EscrowCustomBuyer.sol | 112 +++++++++++++ contracts/src/EscrowUniversal.sol | 31 ---- contracts/src/interfaces/IEscrow.sol | 17 -- contracts/test/EscrowCustomBuyer.t.sol | 207 +++++++++++++++++++++++++ contracts/test/EscrowUniversal.t.sol | 43 ----- 5 files changed, 319 insertions(+), 91 deletions(-) create mode 100644 contracts/src/EscrowCustomBuyer.sol create mode 100644 contracts/test/EscrowCustomBuyer.t.sol diff --git a/contracts/src/EscrowCustomBuyer.sol b/contracts/src/EscrowCustomBuyer.sol new file mode 100644 index 0000000..210327a --- /dev/null +++ b/contracts/src/EscrowCustomBuyer.sol @@ -0,0 +1,112 @@ +// SPDX-License-Identifier: MIT + +/// @authors: [@unknownunknown1, @jaybuidl] +/// @reviewers: [] +/// @auditors: [] +/// @bounties: [] + +pragma solidity 0.8.24; + +import "./EscrowUniversal.sol"; + +/// @title EscrowCustomBuyer. +/// @dev Version of Escrow that allows to specify a buyer when transaction is created. +contract EscrowCustomBuyer is EscrowUniversal { + using SafeERC20 for IERC20; + + /// @dev Constructor. + /// @param _arbitrator The arbitrator of the contract. + /// @param _arbitratorExtraData Extra data for the arbitrator. + /// @param _templateData The dispute template data. + /// @param _templateDataMappings The dispute template data mappings. + /// @param _templateRegistry The dispute template registry. + /// @param _feeTimeout Arbitration fee timeout for the parties. + /// @param _settlementTimeout Settlement timeout for the parties. + constructor( + IArbitratorV2 _arbitrator, + bytes memory _arbitratorExtraData, + string memory _templateData, + string memory _templateDataMappings, + IDisputeTemplateRegistry _templateRegistry, + uint256 _feeTimeout, + uint256 _settlementTimeout + ) EscrowUniversal( + _arbitrator, + _arbitratorExtraData, + _templateData, + _templateDataMappings, + _templateRegistry, + _feeTimeout, + _settlementTimeout + ) {} + + /// @dev Create a native transaction with custom buyer. + /// @param _deadline Time after which a party can automatically execute the arbitrable transaction. + /// @param _transactionUri The IPFS Uri Hash of the transaction. + /// @param _buyer Buyer's address. + /// @param _seller The recipient of the transaction. + /// @return transactionID The index of the transaction. + function createNativeTransactionCustomBuyer( + uint256 _deadline, + string memory _transactionUri, + address payable _buyer, + address payable _seller + ) external payable shouldNotExceedCap(NATIVE, msg.value) returns (uint256 transactionID) { + Transaction storage transaction = transactions.push(); + transaction.buyer = _buyer; + transaction.seller = _seller; + /// Note that in this version of the contract the amount is provided by the caller, not by the buyer. + transaction.amount = msg.value; + transaction.token = NATIVE; + transaction.deadline = _deadline; + + transactionID = transactions.length - 1; + + emit NativeTransactionCreated( + transactionID, + _transactionUri, + _buyer, + _seller, + msg.value, + transaction.deadline + ); + } + + /// @dev Create an ERC20 transaction with custom buyer address. + /// @param _amount The amount of tokens in this transaction. + /// @param _token The ERC20 token contract. + /// @param _deadline Time after which a party can automatically execute the arbitrable transaction. + /// @param _transactionUri The IPFS Uri Hash of the transaction. + /// @param _buyer Buyer's address. + /// @param _seller The recipient of the transaction. + /// @return transactionID The index of the transaction. + function createERC20TransactionCustomBuyer( + uint256 _amount, + IERC20 _token, + uint256 _deadline, + string memory _transactionUri, + address payable _buyer, + address payable _seller + ) external shouldNotExceedCap(_token, _amount) returns (uint256 transactionID) { + // Transfers token from sender wallet to contract. Note that in this version of the contract the amount is provided by the caller, not by the buyer. + if (!_token.safeTransferFrom(msg.sender, address(this), _amount)) revert TokenTransferFailed(); + Transaction storage transaction = transactions.push(); + transaction.buyer = _buyer; + transaction.seller = _seller; + transaction.amount = _amount; + transaction.token = _token; + transaction.deadline = _deadline; + + transactionID = transactions.length - 1; + + emit ERC20TransactionCreated( + transactionID, + _transactionUri, + _buyer, + _seller, + _token, + _amount, + transaction.deadline + ); + } +} diff --git a/contracts/src/EscrowUniversal.sol b/contracts/src/EscrowUniversal.sol index 144b134..09acdd1 100644 --- a/contracts/src/EscrowUniversal.sol +++ b/contracts/src/EscrowUniversal.sol @@ -186,37 +186,6 @@ contract EscrowUniversal is IEscrow, IArbitrableV2 { ); } - /// @inheritdoc IEscrow - function createERC20TransactionCustomBuyer( - uint256 _amount, - IERC20 _token, - uint256 _deadline, - string memory _transactionUri, - address payable _buyer, - address payable _seller - ) external override shouldNotExceedCap(_token, _amount) returns (uint256 transactionID) { - // Transfers token from sender wallet to contract. Note that the amount is provided by the caller, not by the buyer. - if (!_token.safeTransferFrom(msg.sender, address(this), _amount)) revert TokenTransferFailed(); - Transaction storage transaction = transactions.push(); - transaction.buyer = _buyer; - transaction.seller = _seller; - transaction.amount = _amount; - transaction.token = _token; - transaction.deadline = _deadline; - - transactionID = transactions.length - 1; - - emit ERC20TransactionCreated( - transactionID, - _transactionUri, - _buyer, - _seller, - _token, - _amount, - transaction.deadline - ); - } - /// @inheritdoc IEscrow function pay(uint256 _transactionID, uint256 _amount) external override { Transaction storage transaction = transactions[_transactionID]; diff --git a/contracts/src/interfaces/IEscrow.sol b/contracts/src/interfaces/IEscrow.sol index f7902a6..252df49 100644 --- a/contracts/src/interfaces/IEscrow.sol +++ b/contracts/src/interfaces/IEscrow.sol @@ -99,23 +99,6 @@ interface IEscrow { address payable _seller ) external returns (uint256 transactionID); - /// @dev Create an ERC20 transaction with custom buyer address. - /// @param _amount The amount of tokens in this transaction. - /// @param _token The ERC20 token contract. - /// @param _deadline Time after which a party can automatically execute the arbitrable transaction. - /// @param _transactionUri The IPFS Uri Hash of the transaction. - /// @param _buyer Buyer's address. - /// @param _seller The recipient of the transaction. - /// @return transactionID The index of the transaction. - function createERC20TransactionCustomBuyer( - uint256 _amount, - IERC20 _token, - uint256 _deadline, - string memory _transactionUri, - address payable _buyer, - address payable _seller - ) external returns (uint256 transactionID); - /// @dev Pay seller. To be called if the good or service is provided. /// @param _transactionID The index of the transaction. /// @param _amount Amount to pay in wei. diff --git a/contracts/test/EscrowCustomBuyer.t.sol b/contracts/test/EscrowCustomBuyer.t.sol new file mode 100644 index 0000000..044353a --- /dev/null +++ b/contracts/test/EscrowCustomBuyer.t.sol @@ -0,0 +1,207 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {Test} from "forge-std/Test.sol"; +import {console} from "forge-std/console.sol"; // Import the console for logging +import {EscrowCustomBuyer} from "../src/EscrowCustomBuyer.sol"; +import {ArbitratorMock} from "../src/test/ArbitratorMock.sol"; +import {DisputeTemplateRegistryMock} from "../src/test/DisputeTemplateRegistryMock.sol"; +import {TestERC20} from "../src/test/TestERC20.sol"; +import "../src/interfaces/Types.sol"; + +contract EscrowCustomBuyerTest is Test { + + event NativeTransactionCreated( + uint256 indexed _transactionID, + string _transactionUri, + address indexed _buyer, + address indexed _seller, + uint256 _amount, + uint256 _deadline + ); + + event ERC20TransactionCreated( + uint256 indexed _transactionID, + string _transactionUri, + address indexed _buyer, + address indexed _seller, + IERC20 _token, + uint256 _amount, + uint256 _deadline + ); + + EscrowCustomBuyer escrow; + ArbitratorMock arbitrator; + TestERC20 escrowToken; + DisputeTemplateRegistryMock registry; + + address governor; + address buyer; + address seller; + address other; + + uint256 feeTimeout; + uint256 settlementTimeout; + bytes arbitratorExtraData; + string templateData; + string templateDataMappings; + uint256 arbitrationCost; + + uint256 totalSupply = 1000000 ether; + uint256 txValue = 0.5 ether; + uint256 txTimeout = 1000; + string txUri = "escrowTxUri"; + + function setUp() public { + governor = msg.sender; + buyer = vm.addr(1); + seller = vm.addr(2); + other = vm.addr(9); + + vm.deal(buyer, 10 ether); + + feeTimeout = 200; + settlementTimeout = 400; + + // Extradata is irrelevant for mock arbitrator and doesn't influence the arbitration cost. + arbitratorExtraData = "0xfa"; + templateData = "AAA"; + templateDataMappings = "BBB"; + arbitrationCost = 0.03 ether; + + arbitrator = new ArbitratorMock(arbitrationCost); + escrowToken = new TestERC20("Test", "TST"); + registry = new DisputeTemplateRegistryMock(); + + vm.prank(governor); + escrow = new EscrowCustomBuyer( + arbitrator, + arbitratorExtraData, + templateData, + templateDataMappings, + registry, + feeTimeout, + settlementTimeout + ); + + escrowToken.transfer(buyer, 1 ether); + vm.prank(buyer); + escrowToken.approve(address(escrow), 1 ether); + + vm.prank(governor); + escrow.changeAmountCap(NATIVE, txValue); + vm.prank(governor); + escrow.changeAmountCap(escrowToken, txValue); + } + + function test_setUp() public { + assertEq(escrow.governor(), msg.sender, "Wrong governor"); + assertEq(address(escrow.arbitrator()), address(arbitrator), "Wrong arbitrator"); + assertEq(escrow.arbitratorExtraData(), "0xfa", "Wrong extra data"); + assertEq(address(escrow.templateRegistry()), address(registry), "Wrong template registry"); + assertEq(escrow.feeTimeout(), 200, "Wrong feeTimeout"); + assertEq(escrow.settlementTimeout(), 400, "Wrong settlementTimeout"); + assertEq(escrow.templateId(), 0, "Wrong templateId"); + assertEq(escrow.AMOUNT_OF_CHOICES(), 2, "Wrong number of choices"); + assertEq(escrow.getTransactionCount(), 0, "Transaction count should be 0"); + + + assertEq(arbitrator.arbitrationCost(arbitratorExtraData), 0.03 ether, "Wrong arbitration cost"); + + assertEq(escrowToken.name(), "Test", "Wrong token name"); + assertEq(escrowToken.symbol(), "TST", "Wrong token symbol"); + assertEq(escrowToken.totalSupply(), 1000000 ether, "Wrong total supply"); + assertEq(escrowToken.balanceOf(address(this)), 999999 ether, "Wrong token balance of this contract"); + assertEq(escrowToken.balanceOf(buyer), 1 ether, "Wrong token balance of the buyer"); + + assertEq(registry.templates(), 1, "Wrong templates index in the registry"); + + assertEq(escrow.amountCaps(NATIVE), 0.5 ether, "Wrong amount cap NATIVE"); + assertEq(escrow.amountCaps(escrowToken), 0.5 ether, "Wrong amount cap for escrowToken"); + } + + function test_createNativeTransactionCustomBuyer() public { + uint256 deadline = block.timestamp + txTimeout; + uint256 txId; + vm.prank(buyer); + vm.expectEmit(true, true, true, true); + emit NativeTransactionCreated(txId, txUri, other, seller, 0.5 ether, deadline); + escrow.createNativeTransactionCustomBuyer{value: txValue}(deadline, txUri, payable(other), payable(seller)); + + ( + address escrowBuyer, + address escrowSeller, + uint256 amount, + uint256 settlementBuyer, + uint256 settlementSeller, + uint256 escrowdeadline, + uint256 disputeId, + uint256 buyerFee, + uint256 sellerFee, + uint256 lastFeePaymentTime, + Status status, + IERC20 token + ) = escrow.transactions(txId); + + assertEq(escrowBuyer, other, "Wrong custom buyer address"); + assertEq(escrowSeller, seller, "Wrong seller address"); + assertEq(amount, 0.5 ether, "Wrong escrow amount"); + assertEq(settlementBuyer, 0, "settlementBuyer should be 0"); + assertEq(settlementSeller, 0, "settlementSeller should be 0"); + assertEq(escrowdeadline, block.timestamp + 1000, "Wrong deadline"); + assertEq(disputeId, 0, "disputeId should be 0"); + assertEq(sellerFee, 0, "sellerFee should be 0"); + assertEq(lastFeePaymentTime, 0, "lastFeePaymentTime should be 0"); + assertEq(uint256(status), uint256(Status.NoDispute), "Wrong status"); + assertEq(address(token), address(NATIVE), "Should be 0 token"); + assertEq(escrow.getTransactionCount(), 1, "Wrong transaction count"); + + assertEq(address(escrow).balance, 0.5 ether, "Wrong balance of the contract"); + assertEq(buyer.balance, 9.5 ether, "Wrong balance of the buyer"); // tx creator + assertEq(seller.balance, 0, "Seller balance should be 0"); + assertEq(other.balance, 0, "Balance of custom buyer should be 0"); // custom buyer did not have balance of his own + } + + function test_createERC20TransactionCustomBuyer() public { + uint256 deadline = block.timestamp + txTimeout; + uint256 txId; + vm.prank(buyer); + vm.expectEmit(true, true, true, true); + // Pay a bit less to differ between tests + emit ERC20TransactionCreated(txId, txUri, other, seller, escrowToken, 0.4 ether, deadline); + escrow.createERC20TransactionCustomBuyer(0.4 ether, escrowToken, deadline, txUri, payable(other), payable(seller)); + + ( + address escrowBuyer, + address escrowSeller, + uint256 amount, + uint256 settlementBuyer, + uint256 settlementSeller, + uint256 escrowdeadline, + uint256 disputeId, + uint256 buyerFee, + uint256 sellerFee, + uint256 lastFeePaymentTime, + Status status, + IERC20 token + ) = escrow.transactions(txId); + + assertEq(escrowBuyer, other, "Wrong custom buyer address"); + assertEq(escrowSeller, seller, "Wrong seller address"); + assertEq(amount, 0.4 ether, "Wrong escrow amount"); + assertEq(settlementBuyer, 0, "settlementBuyer should be 0"); + assertEq(settlementSeller, 0, "settlementSeller should be 0"); + assertEq(escrowdeadline, block.timestamp + 1000, "Wrong deadline"); + assertEq(disputeId, 0, "disputeId should be 0"); + assertEq(sellerFee, 0, "sellerFee should be 0"); + assertEq(lastFeePaymentTime, 0, "lastFeePaymentTime should be 0"); + assertEq(uint256(status), uint256(Status.NoDispute), "Wrong status"); + assertEq(address(token), address(escrowToken), "Wrong token address"); + assertEq(escrow.getTransactionCount(), 1, "Wrong transaction count"); + + assertEq(escrowToken.balanceOf(address(escrow)), 0.4 ether, "Wrong token balance of the escrow"); + assertEq(escrowToken.balanceOf(buyer), 0.6 ether, "Wrong token balance of buyer"); // tx creator + assertEq(escrowToken.balanceOf(seller), 0, "Balance of seller should be 0"); + assertEq(escrowToken.balanceOf(other), 0, "Balance of custom buyer should be 0"); // custom buyer did not have balance of his own + } +} diff --git a/contracts/test/EscrowUniversal.t.sol b/contracts/test/EscrowUniversal.t.sol index c7c199a..e01d936 100644 --- a/contracts/test/EscrowUniversal.t.sol +++ b/contracts/test/EscrowUniversal.t.sol @@ -380,49 +380,6 @@ contract EscrowUniversalTest is Test { assertEq(escrowToken.balanceOf(seller), 0, "Balance of seller should be 0"); } - function test_createERC20TransactionCustomBuyer() public { - uint256 deadline = block.timestamp + txTimeout; - uint256 txId; - vm.prank(buyer); - vm.expectEmit(true, true, true, true); - // Pay a bit less to differ between tests - emit ERC20TransactionCreated(txId, txUri, other, seller, escrowToken, 0.4 ether, deadline); - escrow.createERC20TransactionCustomBuyer(0.4 ether, escrowToken, deadline, txUri, payable(other), payable(seller)); - - ( - address escrowBuyer, - address escrowSeller, - uint256 amount, - uint256 settlementBuyer, - uint256 settlementSeller, - uint256 escrowdeadline, - uint256 disputeId, - uint256 buyerFee, - uint256 sellerFee, - uint256 lastFeePaymentTime, - Status status, - IERC20 token - ) = escrow.transactions(txId); - - assertEq(escrowBuyer, other, "Wrong custom buyer address"); - assertEq(escrowSeller, seller, "Wrong seller address"); - assertEq(amount, 0.4 ether, "Wrong escrow amount"); - assertEq(settlementBuyer, 0, "settlementBuyer should be 0"); - assertEq(settlementSeller, 0, "settlementSeller should be 0"); - assertEq(escrowdeadline, block.timestamp + 1000, "Wrong deadline"); - assertEq(disputeId, 0, "disputeId should be 0"); - assertEq(sellerFee, 0, "sellerFee should be 0"); - assertEq(lastFeePaymentTime, 0, "lastFeePaymentTime should be 0"); - assertEq(uint256(status), uint256(Status.NoDispute), "Wrong status"); - assertEq(address(token), address(escrowToken), "Wrong token address"); - assertEq(escrow.getTransactionCount(), 1, "Wrong transaction count"); - - assertEq(escrowToken.balanceOf(address(escrow)), 0.4 ether, "Wrong token balance of the escrow"); - assertEq(escrowToken.balanceOf(buyer), 0.6 ether, "Wrong token balance of buyer"); // tx creator - assertEq(escrowToken.balanceOf(seller), 0, "Balance of seller should be 0"); - assertEq(escrowToken.balanceOf(other), 0, "Balance of custom buyer should be 0"); // custom buyer did not have balance of his own - } - function test_createNativeTransaction_approvalMissing() public { uint256 deadline = block.timestamp + txTimeout; From 1fbe1faa34f19939188b55fecad0901ce9658e8f Mon Sep 17 00:00:00 2001 From: kemuru <102478601+kemuru@users.noreply.github.com> Date: Thu, 24 Jul 2025 02:01:52 +0200 Subject: [PATCH 07/13] feat: buffer between delivery deadline and dispute deadline --- .../InfoCards/BufferPeriodWarning.tsx | 12 ++++++++++++ .../MyTransactions/TransactionDetails/index.tsx | 17 ++++++++++++++++- .../NavigationButtons/DepositPaymentButton.tsx | 13 ++++++++++--- web/src/utils/bufferRules.ts | 12 ++++++++++++ 4 files changed, 50 insertions(+), 4 deletions(-) create mode 100644 web/src/pages/MyTransactions/TransactionDetails/InfoCards/BufferPeriodWarning.tsx create mode 100644 web/src/utils/bufferRules.ts diff --git a/web/src/pages/MyTransactions/TransactionDetails/InfoCards/BufferPeriodWarning.tsx b/web/src/pages/MyTransactions/TransactionDetails/InfoCards/BufferPeriodWarning.tsx new file mode 100644 index 0000000..2b3bed0 --- /dev/null +++ b/web/src/pages/MyTransactions/TransactionDetails/InfoCards/BufferPeriodWarning.tsx @@ -0,0 +1,12 @@ +import React from "react"; +import { AlertMessage } from "@kleros/ui-components-library"; + +interface Props { + message: string; +} + +const BufferPeriodWarning: React.FC = ({ message }) => ( + +); + +export default BufferPeriodWarning; \ No newline at end of file diff --git a/web/src/pages/MyTransactions/TransactionDetails/index.tsx b/web/src/pages/MyTransactions/TransactionDetails/index.tsx index 96303d0..0ffff18 100644 --- a/web/src/pages/MyTransactions/TransactionDetails/index.tsx +++ b/web/src/pages/MyTransactions/TransactionDetails/index.tsx @@ -5,6 +5,8 @@ import { useParams } from "react-router-dom"; import { formatEther } from "viem"; import { useTransactionDetailsContext } from "context/TransactionDetailsContext"; import { isUndefined } from "utils/index"; +import { formatTimeoutDuration } from "utils/formatTimeoutDuration"; +import { pickBufferFor } from "utils/bufferRules"; import PreviewCard from "components/PreviewCard"; import WasItFulfilled from "./WasItFulfilled"; import InfoCards from "./InfoCards"; @@ -14,6 +16,7 @@ import { useReadKlerosCoreArbitrationCost } from "hooks/contracts/generated"; import { useNativeTokenSymbol } from "hooks/useNativeTokenSymbol"; import useFetchIpfsJson from "hooks/useFetchIpfsJson"; import { useTokenMetadata } from "hooks/useTokenMetadata"; +import BufferPeriodWarning from "./InfoCards/BufferPeriodWarning"; const Container = styled.div``; @@ -70,10 +73,22 @@ const TransactionDetails: React.FC = () => { } }, [transactionDetails, setTransactionDetails, assetSymbol]); + const disputeDeadlineMs = deadline * 1000; + const bufferSecNumber = transactionInfo?.bufferSec ?? pickBufferFor(timestamp); + const deliveryDeadlineMs = disputeDeadlineMs - bufferSecNumber * 1000; + const now = Date.now(); + const inBuffer = now > deliveryDeadlineMs && now < disputeDeadlineMs; + const secondsLeft = Math.max(0, Math.floor((disputeDeadlineMs - now) / 1000)); + return (
Transaction #{id}
+ {inBuffer && ( + + )} { sellerAddress={seller} transactionCreationTimestamp={timestamp} sendingQuantity={!isUndefined(amount) ? formatEther(amount) : ""} - deadline={deadline * 1000} + deadline={deliveryDeadlineMs} overrideIsList={false} amount={!isUndefined(amount) ? formatEther(amount) : ""} isPreview={false} diff --git a/web/src/pages/NewTransaction/NavigationButtons/DepositPaymentButton.tsx b/web/src/pages/NewTransaction/NavigationButtons/DepositPaymentButton.tsx index 036b3b1..ff8d5ea 100644 --- a/web/src/pages/NewTransaction/NavigationButtons/DepositPaymentButton.tsx +++ b/web/src/pages/NewTransaction/NavigationButtons/DepositPaymentButton.tsx @@ -22,6 +22,7 @@ import { import { parseEther, parseUnits } from "viem"; import { normalize } from "viem/ens"; import { isUndefined } from "utils/index"; +import { pickBufferFor } from "utils/bufferRules"; import { wrapWithToast } from "utils/wrapWithToast"; import { ethAddressPattern } from "utils/validateAddress"; import { useQueryRefetch } from "hooks/useQueryRefetch"; @@ -60,7 +61,13 @@ const DepositPaymentButton: React.FC = () => { const [isApproved, setIsApproved] = useState(false); const { address, chain } = useAccount(); const ensResult = useEnsAddress({ name: normalize(sellerAddress), chainId: 1 }); - const deadlineTimestamp = useMemo(() => BigInt(Math.floor(new Date(deadline).getTime() / 1000)), [deadline]); + const deliveryDeadlineTimestamp = useMemo( + () => BigInt(Math.floor(new Date(deadline).getTime() / 1000)), + [deadline] + ); + + const bufferSec = useMemo(() => BigInt(pickBufferFor(Number(deliveryDeadlineTimestamp))), [deliveryDeadlineTimestamp]); + const disputeDeadlineTimestamp = useMemo(() => deliveryDeadlineTimestamp + bufferSec, [deliveryDeadlineTimestamp, bufferSec]); const isNativeTransaction = sendingToken?.address === "native"; const transactionValue = useMemo( () => (isNativeTransaction ? parseEther(sendingQuantity) : parseUnits(sendingQuantity, 18)), @@ -114,7 +121,7 @@ const DepositPaymentButton: React.FC = () => { query: { enabled: isNativeTransaction && ethAddressPattern.test(finalRecipientAddress) && !insufficientBalance, }, - args: [deadlineTimestamp, transactionUri, finalRecipientAddress], + args: [disputeDeadlineTimestamp, transactionUri, finalRecipientAddress], value: transactionValue, }); @@ -134,7 +141,7 @@ const DepositPaymentButton: React.FC = () => { args: [ transactionValue, sendingToken?.address as `0x${string}`, - deadlineTimestamp, + disputeDeadlineTimestamp, transactionUri, finalRecipientAddress as `0x${string}`, ], diff --git a/web/src/utils/bufferRules.ts b/web/src/utils/bufferRules.ts new file mode 100644 index 0000000..3cea19e --- /dev/null +++ b/web/src/utils/bufferRules.ts @@ -0,0 +1,12 @@ +export type BufferRule = { fromUnixSec: number; bufferSec: number }; + +export const BUFFER_RULES: BufferRule[] = [ + { fromUnixSec: 0, bufferSec: 0 }, // there was no buffer between delivery deadline and dispute deadline in the beginning of Escrow V2 + { fromUnixSec: 1753315200, bufferSec: 7 * 24 * 60 * 60 } // starts Jul 24 2025 00:00:00 UTC, buffer = 1 week (604800s) +]; + +export const pickBufferFor = (creationUnixSec: number) => + BUFFER_RULES.reduce( + (acc, r) => (creationUnixSec >= r.fromUnixSec ? r.bufferSec : acc), + BUFFER_RULES[0].bufferSec + ); From bac270da1bc57388525bd5d8ee9e4b6dcf33b86b Mon Sep 17 00:00:00 2001 From: kemuru <102478601+kemuru@users.noreply.github.com> Date: Thu, 24 Jul 2025 02:13:56 +0200 Subject: [PATCH 08/13] fix: use creation timestamp instead of deliverydeadline timestamp --- .../NewTransaction/NavigationButtons/DepositPaymentButton.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/src/pages/NewTransaction/NavigationButtons/DepositPaymentButton.tsx b/web/src/pages/NewTransaction/NavigationButtons/DepositPaymentButton.tsx index ff8d5ea..d33d947 100644 --- a/web/src/pages/NewTransaction/NavigationButtons/DepositPaymentButton.tsx +++ b/web/src/pages/NewTransaction/NavigationButtons/DepositPaymentButton.tsx @@ -66,7 +66,7 @@ const DepositPaymentButton: React.FC = () => { [deadline] ); - const bufferSec = useMemo(() => BigInt(pickBufferFor(Number(deliveryDeadlineTimestamp))), [deliveryDeadlineTimestamp]); + const bufferSec = useMemo(() => BigInt(pickBufferFor(Math.floor(Date.now() / 1000))), []); const disputeDeadlineTimestamp = useMemo(() => deliveryDeadlineTimestamp + bufferSec, [deliveryDeadlineTimestamp, bufferSec]); const isNativeTransaction = sendingToken?.address === "native"; const transactionValue = useMemo( From 301fcd7ea2a48c3b58b717aa2e40e5c2f5bb8b0f Mon Sep 17 00:00:00 2001 From: kemuru <102478601+kemuru@users.noreply.github.com> Date: Thu, 24 Jul 2025 02:52:31 +0200 Subject: [PATCH 09/13] fix: ux impro, test 1 year buffer to check retrocompatibility --- .../InfoCards/BufferPeriodWarning.tsx | 38 ++++++++++++++++--- .../TransactionDetails/index.tsx | 9 +---- web/src/utils/bufferRules.ts | 3 +- 3 files changed, 36 insertions(+), 14 deletions(-) diff --git a/web/src/pages/MyTransactions/TransactionDetails/InfoCards/BufferPeriodWarning.tsx b/web/src/pages/MyTransactions/TransactionDetails/InfoCards/BufferPeriodWarning.tsx index 2b3bed0..3071790 100644 --- a/web/src/pages/MyTransactions/TransactionDetails/InfoCards/BufferPeriodWarning.tsx +++ b/web/src/pages/MyTransactions/TransactionDetails/InfoCards/BufferPeriodWarning.tsx @@ -1,12 +1,40 @@ -import React from "react"; +import React, { useEffect, useState, useMemo } from "react"; import { AlertMessage } from "@kleros/ui-components-library"; +import { useAccount } from "wagmi"; +import { useTransactionDetailsContext } from "context/TransactionDetailsContext"; +import { formatTimeoutDuration } from "utils/formatTimeoutDuration"; interface Props { - message: string; + disputeDeadlineMs: number; + deliveryDeadlineMs: number; } -const BufferPeriodWarning: React.FC = ({ message }) => ( - -); +const BufferPeriodWarning: React.FC = ({ disputeDeadlineMs, deliveryDeadlineMs }) => { + const nowMs = Date.now(); + const [now, setNow] = useState(nowMs); + const { address } = useAccount(); + const { seller, buyer } = useTransactionDetailsContext(); + + useEffect(() => { + const id = setInterval(() => setNow(Date.now()), 1000); + return () => clearInterval(id); + }, []); + + const inBuffer = now > deliveryDeadlineMs && now < disputeDeadlineMs; + const secondsLeft = useMemo(() => Math.max(0, Math.floor((disputeDeadlineMs - now) / 1000)), [disputeDeadlineMs, now]); + + if (!inBuffer) return null; + + const isBuyerConnected = address?.toLowerCase() === buyer; + const isSellerConnected = address?.toLowerCase() === seller; + + const msgBuyer = `You have ${formatTimeoutDuration(secondsLeft)} to release the payment, reach a settlement, or raise a dispute.`; + const msgSeller = `You have ${formatTimeoutDuration(secondsLeft)} to reach a settlement or raise a dispute.`; + const msgGeneric = `There is ${formatTimeoutDuration(secondsLeft)} to either reach a settlement with the other party or raise a dispute.`; + + const message = isBuyerConnected ? msgBuyer : isSellerConnected ? msgSeller : msgGeneric; + + return ; +}; export default BufferPeriodWarning; \ No newline at end of file diff --git a/web/src/pages/MyTransactions/TransactionDetails/index.tsx b/web/src/pages/MyTransactions/TransactionDetails/index.tsx index 0ffff18..28e6c78 100644 --- a/web/src/pages/MyTransactions/TransactionDetails/index.tsx +++ b/web/src/pages/MyTransactions/TransactionDetails/index.tsx @@ -5,7 +5,6 @@ import { useParams } from "react-router-dom"; import { formatEther } from "viem"; import { useTransactionDetailsContext } from "context/TransactionDetailsContext"; import { isUndefined } from "utils/index"; -import { formatTimeoutDuration } from "utils/formatTimeoutDuration"; import { pickBufferFor } from "utils/bufferRules"; import PreviewCard from "components/PreviewCard"; import WasItFulfilled from "./WasItFulfilled"; @@ -77,18 +76,12 @@ const TransactionDetails: React.FC = () => { const bufferSecNumber = transactionInfo?.bufferSec ?? pickBufferFor(timestamp); const deliveryDeadlineMs = disputeDeadlineMs - bufferSecNumber * 1000; const now = Date.now(); - const inBuffer = now > deliveryDeadlineMs && now < disputeDeadlineMs; - const secondsLeft = Math.max(0, Math.floor((disputeDeadlineMs - now) / 1000)); return (
Transaction #{id}
- {inBuffer && ( - - )} + From 46b416b7c2f084351895584098ac175bf28fe614 Mon Sep 17 00:00:00 2001 From: kemuru <102478601+kemuru@users.noreply.github.com> Date: Thu, 24 Jul 2025 02:59:02 +0200 Subject: [PATCH 10/13] chore: revert test buffer --- web/src/pages/MyTransactions/TransactionDetails/index.tsx | 1 - web/src/utils/bufferRules.ts | 1 - 2 files changed, 2 deletions(-) diff --git a/web/src/pages/MyTransactions/TransactionDetails/index.tsx b/web/src/pages/MyTransactions/TransactionDetails/index.tsx index 28e6c78..cb0ff9f 100644 --- a/web/src/pages/MyTransactions/TransactionDetails/index.tsx +++ b/web/src/pages/MyTransactions/TransactionDetails/index.tsx @@ -75,7 +75,6 @@ const TransactionDetails: React.FC = () => { const disputeDeadlineMs = deadline * 1000; const bufferSecNumber = transactionInfo?.bufferSec ?? pickBufferFor(timestamp); const deliveryDeadlineMs = disputeDeadlineMs - bufferSecNumber * 1000; - const now = Date.now(); return ( diff --git a/web/src/utils/bufferRules.ts b/web/src/utils/bufferRules.ts index da1fc59..05ef324 100644 --- a/web/src/utils/bufferRules.ts +++ b/web/src/utils/bufferRules.ts @@ -3,7 +3,6 @@ export type BufferRule = { fromUnixSec: number; bufferSec: number }; export const BUFFER_RULES: BufferRule[] = [ { fromUnixSec: 0, bufferSec: 0 }, // there was no buffer between delivery deadline and dispute deadline in the beginning of Escrow V2 { fromUnixSec: 1753315200, bufferSec: 7 * 24 * 60 * 60 }, // starts Jul 24 2025 00:00:00 UTC, buffer = 1 week (604800s) - { fromUnixSec: 1753318200, bufferSec: 365 * 24 * 60 * 60 } // starts Jul 24 2025 00:50:00 UTC, buffer = 1 year (testing) ]; export const pickBufferFor = (creationUnixSec: number) => From 2ef44e84013584faf25e7042a90c8659be13e2e8 Mon Sep 17 00:00:00 2001 From: kemuru <102478601+kemuru@users.noreply.github.com> Date: Fri, 25 Jul 2025 01:00:21 +0200 Subject: [PATCH 11/13] feat: hide the buffer warning if the transaction status moved away from nodispute --- .../InfoCards/BufferPeriodWarning.tsx | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/web/src/pages/MyTransactions/TransactionDetails/InfoCards/BufferPeriodWarning.tsx b/web/src/pages/MyTransactions/TransactionDetails/InfoCards/BufferPeriodWarning.tsx index 3071790..6a91ced 100644 --- a/web/src/pages/MyTransactions/TransactionDetails/InfoCards/BufferPeriodWarning.tsx +++ b/web/src/pages/MyTransactions/TransactionDetails/InfoCards/BufferPeriodWarning.tsx @@ -13,15 +13,21 @@ const BufferPeriodWarning: React.FC = ({ disputeDeadlineMs, deliveryDeadl const nowMs = Date.now(); const [now, setNow] = useState(nowMs); const { address } = useAccount(); - const { seller, buyer } = useTransactionDetailsContext(); + const { buyer, seller, status } = useTransactionDetailsContext(); + + const hidePermanently = status !== "NoDispute"; useEffect(() => { + if (hidePermanently) return; const id = setInterval(() => setNow(Date.now()), 1000); return () => clearInterval(id); - }, []); + }, [hidePermanently]); - const inBuffer = now > deliveryDeadlineMs && now < disputeDeadlineMs; - const secondsLeft = useMemo(() => Math.max(0, Math.floor((disputeDeadlineMs - now) / 1000)), [disputeDeadlineMs, now]); + const inBuffer = !hidePermanently && now > deliveryDeadlineMs && now < disputeDeadlineMs; + const secondsLeft = useMemo( + () => Math.max(0, Math.floor((disputeDeadlineMs - now) / 1000)), + [disputeDeadlineMs, now] + ); if (!inBuffer) return null; From 2686fa7244643878215a93d6db024b03dff1e33f Mon Sep 17 00:00:00 2001 From: jaybuidl Date: Fri, 25 Jul 2025 16:48:22 +0200 Subject: [PATCH 12/13] chore: changeArbitrator script --- contracts/hardhat.config.ts | 1 + contracts/scripts/changeArbitrator.ts | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 contracts/scripts/changeArbitrator.ts diff --git a/contracts/hardhat.config.ts b/contracts/hardhat.config.ts index 4010669..a2f1eec 100644 --- a/contracts/hardhat.config.ts +++ b/contracts/hardhat.config.ts @@ -14,6 +14,7 @@ import "hardhat-docgen"; // import "hardhat-tracer"; // prevents hardhat-deploy from finding chalk... require("./scripts/setDisputeTemplate"); require("./scripts/getPayoutMessages"); +require("./scripts/changeArbitrator"); dotenv.config(); diff --git a/contracts/scripts/changeArbitrator.ts b/contracts/scripts/changeArbitrator.ts new file mode 100644 index 0000000..1d3e531 --- /dev/null +++ b/contracts/scripts/changeArbitrator.ts @@ -0,0 +1,22 @@ +// import { BigNumber, utils } from "ethers"; +import { task } from "hardhat/config"; +import { getContracts } from "../deploy/utils/getContracts"; + +const parameters = { + arbitrumSepoliaDevnet: {}, + arbitrumSepoliaTestnet: {}, + arbitrum: {}, +}; + +task("change-arbitrator", "Changes the arbitrator").setAction(async (args, hre) => { + const { escrow, klerosCore } = await getContracts(hre); + + console.log("changing Arbitrator..."); + const tx = await escrow.changeArbitrator(klerosCore.target); + await tx.wait().then((receipt) => { + console.log(`changeArbitrator() receipt: ${JSON.stringify(receipt)}`); + }); + + console.log("changing DisputeTemplate..."); + await hre.run("set-dispute-template"); +}); From 8b3cf07266dc63300771977d00b25c9b677b9ca3 Mon Sep 17 00:00:00 2001 From: jaybuidl Date: Fri, 25 Jul 2025 18:26:36 +0200 Subject: [PATCH 13/13] chore: deployment scripts for both escrow contract flavors, custom buyer deployment --- contracts/README.md | 10 +- contracts/README.md.template | 8 +- contracts/deploy/00-escrow-custom-buyer.ts | 15 + contracts/deploy/00-escrow-universal.ts | 15 + contracts/deploy/{00-escrow.ts => shared.ts} | 55 +- contracts/deploy/utils/getContracts.ts | 6 +- .../EscrowCustomBuyer.json | 1651 +++++++++++++++++ .../EscrowViewCustomBuyer.json | 184 ++ contracts/scripts/setDisputeTemplate.ts | 33 +- contracts/src/EscrowCustomBuyer.sol | 33 +- 10 files changed, 1959 insertions(+), 51 deletions(-) create mode 100644 contracts/deploy/00-escrow-custom-buyer.ts create mode 100644 contracts/deploy/00-escrow-universal.ts rename contracts/deploy/{00-escrow.ts => shared.ts} (65%) create mode 100644 contracts/deployments/arbitrumSepoliaDevnet/EscrowCustomBuyer.json create mode 100644 contracts/deployments/arbitrumSepoliaDevnet/EscrowViewCustomBuyer.json diff --git a/contracts/README.md b/contracts/README.md index 45ec74e..dde4e19 100644 --- a/contracts/README.md +++ b/contracts/README.md @@ -19,8 +19,10 @@ Refresh the list of deployed contracts by running `./scripts/generateDeployments ### Devnet #### Arbitrum Sepolia +- [EscrowCustomBuyer](https://sepolia.arbiscan.io/address/0xA01e6B988aeDae1fD4a748D6bfBcB8A438601DeE) - [EscrowUniversal](https://sepolia.arbiscan.io/address/0x5ef185810BCe41c03c9E5ca271B8C91F1024F953) - [EscrowView](https://sepolia.arbiscan.io/address/0x6451046caB9291a919FCba045bf6Bb8E0Bb71467) +- [EscrowViewCustomBuyer](https://sepolia.arbiscan.io/address/0xe0892815E8958f0ad6Dab876995987c4F439954D) ## Getting Started @@ -91,7 +93,8 @@ yarn hardhat node --tags nothing **Shell 2: the deploy script** ```bash -yarn deploy --network localhost --tags Escrow> +yarn deploy --network localhost --tags EscrowUniversal +yarn deploy --network localhost --tags EscrowCustomBuyer ``` #### 2. Deploy to a Public Network Fork @@ -115,7 +118,8 @@ yarn deploy-testnet-fork #### 3. Deploy to Public Testnets ```bash -yarn deploy --network arbitrumSepolia --tags Escrow +yarn deploy --network arbitrumSepolia --tags EscrowUniversal +yarn deploy --network arbitrumSepolia --tags EscrowCustomBuyer ``` The deployed addresses should be displayed to the screen after the deployment is complete. If you missed them, you can always go to the `deployments/` directory and look for the respective file. @@ -129,7 +133,7 @@ Same steps as above but append `Devnet` to the `--network` parameter. **Shell 1: the node** ```bash -yarn hardhat node --tags Escrow +yarn hardhat node --tags EscrowUniversal ``` **Shell 2: the test scripts** diff --git a/contracts/README.md.template b/contracts/README.md.template index 835d26f..68e19c5 100644 --- a/contracts/README.md.template +++ b/contracts/README.md.template @@ -77,7 +77,8 @@ yarn hardhat node --tags nothing **Shell 2: the deploy script** ```bash -yarn deploy --network localhost --tags Escrow> +yarn deploy --network localhost --tags EscrowUniversal +yarn deploy --network localhost --tags EscrowCustomBuyer ``` #### 2. Deploy to a Public Network Fork @@ -101,7 +102,8 @@ yarn deploy-testnet-fork #### 3. Deploy to Public Testnets ```bash -yarn deploy --network arbitrumSepolia --tags Escrow +yarn deploy --network arbitrumSepolia --tags EscrowUniversal +yarn deploy --network arbitrumSepolia --tags EscrowCustomBuyer ``` The deployed addresses should be displayed to the screen after the deployment is complete. If you missed them, you can always go to the `deployments/` directory and look for the respective file. @@ -115,7 +117,7 @@ Same steps as above but append `Devnet` to the `--network` parameter. **Shell 1: the node** ```bash -yarn hardhat node --tags Escrow +yarn hardhat node --tags EscrowUniversal ``` **Shell 2: the test scripts** diff --git a/contracts/deploy/00-escrow-custom-buyer.ts b/contracts/deploy/00-escrow-custom-buyer.ts new file mode 100644 index 0000000..381f692 --- /dev/null +++ b/contracts/deploy/00-escrow-custom-buyer.ts @@ -0,0 +1,15 @@ +import { HardhatRuntimeEnvironment } from "hardhat/types"; +import { DeployFunction } from "hardhat-deploy/types"; +import { HomeChains, isSkipped } from "./utils"; +import deployEscrow from "./shared"; + +const deploy: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { + await deployEscrow(hre, "customBuyer"); +}; + +deploy.tags = ["EscrowCustomBuyer"]; +deploy.skip = async ({ network }) => { + return isSkipped(network, !HomeChains[network.config.chainId ?? 0]); +}; + +export default deploy; diff --git a/contracts/deploy/00-escrow-universal.ts b/contracts/deploy/00-escrow-universal.ts new file mode 100644 index 0000000..ddc6db2 --- /dev/null +++ b/contracts/deploy/00-escrow-universal.ts @@ -0,0 +1,15 @@ +import { HardhatRuntimeEnvironment } from "hardhat/types"; +import { DeployFunction } from "hardhat-deploy/types"; +import { HomeChains, isSkipped } from "./utils"; +import deployEscrow from "./shared"; + +const deploy: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { + await deployEscrow(hre, "universal"); +}; + +deploy.tags = ["EscrowUniversal"]; +deploy.skip = async ({ network }) => { + return isSkipped(network, !HomeChains[network.config.chainId ?? 0]); +}; + +export default deploy; diff --git a/contracts/deploy/00-escrow.ts b/contracts/deploy/shared.ts similarity index 65% rename from contracts/deploy/00-escrow.ts rename to contracts/deploy/shared.ts index 4c30f88..d54ac1b 100644 --- a/contracts/deploy/00-escrow.ts +++ b/contracts/deploy/shared.ts @@ -1,25 +1,54 @@ import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { DeployFunction } from "hardhat-deploy/types"; -import { HomeChains, isSkipped } from "./utils"; +import { HomeChains } from "./utils"; import { EscrowUniversal } from "../typechain-types"; import { getArbitratorContracts } from "./utils/getContracts"; -const config = { +export type EscrowDeployment = { + escrow: string; + view: string; +}; + +export type EscrowDeployments = { + universal: EscrowDeployment; + customBuyer?: EscrowDeployment; +}; + +export const config = { arbitrumSepoliaDevnet: { feeTimeout: 600, // 10 minutes settlementTimeout: 600, // 10 minutes jurors: 1, courtId: 1, + escrowDeployments: { + universal: { + escrow: "EscrowUniversal", + view: "EscrowView", + }, + customBuyer: { + escrow: "EscrowCustomBuyer", + view: "EscrowViewCustomBuyer", + }, + } satisfies EscrowDeployments, }, arbitrum: { feeTimeout: 302400, // 84 hours settlementTimeout: 172800, // 48 hours jurors: 3, courtId: 1, + escrowDeployments: { + universal: { + escrow: "EscrowUniversal", + view: "EscrowView", + }, + customBuyer: undefined, + } satisfies EscrowDeployments, }, }; -const deploy: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { +const deployEscrow = async ( + hre: HardhatRuntimeEnvironment, + escrowDeployment: keyof EscrowDeployments +) => { const { deployments, getNamedAccounts, getChainId, ethers, network } = hre; const { deploy } = deployments; @@ -29,10 +58,10 @@ const deploy: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { console.log("deploying to %s with deployer %s", HomeChains[chainId], deployer); const { disputeTemplateRegistry, klerosCore } = await getArbitratorContracts(hre); - const { feeTimeout, settlementTimeout, jurors, courtId } = config[network.name]; + const { feeTimeout, settlementTimeout, jurors, courtId, escrowDeployments } = config[network.name]; const extraData = ethers.AbiCoder.defaultAbiCoder().encode(["uint96", "uint96"], [courtId, jurors]); - await deploy("EscrowUniversal", { + await deploy(escrowDeployments[escrowDeployment].escrow, { from: deployer, args: [ klerosCore.target, @@ -47,7 +76,7 @@ const deploy: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { }); // Set the value cap to about USD 1000 - const escrow = (await ethers.getContract("EscrowUniversal")) as EscrowUniversal; + const escrow = (await ethers.getContract(escrowDeployments[escrowDeployment].escrow)) as EscrowUniversal; const WETH = await deployments.get("WETH"); const DAI = await deployments.get("DAI"); const PNK = await deployments.getOrNull("PNK"); @@ -72,17 +101,13 @@ const deploy: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { await escrow.changeAmountCap(token, cap); } - await deploy("EscrowView", { + await deploy(escrowDeployments[escrowDeployment].view, { + contract: "EscrowView", from: deployer, args: [escrow.target], - gasLimit: 50000000, + gasLimit: 30000000, log: true, }); }; -deploy.tags = ["Escrow"]; -deploy.skip = async ({ network }) => { - return isSkipped(network, !HomeChains[network.config.chainId ?? 0]); -}; - -export default deploy; +export default deployEscrow; diff --git a/contracts/deploy/utils/getContracts.ts b/contracts/deploy/utils/getContracts.ts index 1de5078..78b4c53 100644 --- a/contracts/deploy/utils/getContracts.ts +++ b/contracts/deploy/utils/getContracts.ts @@ -1,6 +1,6 @@ import { HardhatRuntimeEnvironment } from "hardhat/types"; import { DeploymentName, getContractsEthers as _getArbitratorContracts } from "@kleros/kleros-v2-contracts"; -import { EscrowView, EscrowUniversal } from "../../typechain-types"; +import { EscrowView, EscrowUniversal, EscrowCustomBuyer } from "../../typechain-types"; const NETWORK_TO_DEPLOYMENT: Record = { arbitrumSepoliaDevnet: "devnet", @@ -24,5 +24,7 @@ export const getContracts = async (hre: HardhatRuntimeEnvironment) => { const { klerosCore, disputeTemplateRegistry } = await getArbitratorContracts(hre); const escrow = await ethers.getContract("EscrowUniversal"); const view = await ethers.getContract("EscrowView"); - return { escrow, view, disputeTemplateRegistry, klerosCore }; + const escrowCustomBuyer = await ethers.getContract("EscrowCustomBuyer"); + const customBuyerView = await ethers.getContract("EscrowViewCustomBuyer"); + return { escrow, view, escrowCustomBuyer, customBuyerView, disputeTemplateRegistry, klerosCore }; }; diff --git a/contracts/deployments/arbitrumSepoliaDevnet/EscrowCustomBuyer.json b/contracts/deployments/arbitrumSepoliaDevnet/EscrowCustomBuyer.json new file mode 100644 index 0000000..110adb8 --- /dev/null +++ b/contracts/deployments/arbitrumSepoliaDevnet/EscrowCustomBuyer.json @@ -0,0 +1,1651 @@ +{ + "address": "0xA01e6B988aeDae1fD4a748D6bfBcB8A438601DeE", + "abi": [ + { + "inputs": [ + { + "internalType": "contract IArbitratorV2", + "name": "_arbitrator", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_arbitratorExtraData", + "type": "bytes" + }, + { + "internalType": "string", + "name": "_templateData", + "type": "string" + }, + { + "internalType": "string", + "name": "_templateDataMappings", + "type": "string" + }, + { + "internalType": "contract IDisputeTemplateRegistry", + "name": "_templateRegistry", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_feeTimeout", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_settlementTimeout", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "AmountExceedsCap", + "type": "error" + }, + { + "inputs": [], + "name": "ArbitratorOnly", + "type": "error" + }, + { + "inputs": [], + "name": "BuyerFeeNotCoverArbitrationCosts", + "type": "error" + }, + { + "inputs": [], + "name": "BuyerOnly", + "type": "error" + }, + { + "inputs": [], + "name": "BuyerOrSellerOnly", + "type": "error" + }, + { + "inputs": [], + "name": "DeadlineNotPassed", + "type": "error" + }, + { + "inputs": [], + "name": "DisputeAlreadyResolved", + "type": "error" + }, + { + "inputs": [], + "name": "GovernorOnly", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidRuling", + "type": "error" + }, + { + "inputs": [], + "name": "MaximumPaymentAmountExceeded", + "type": "error" + }, + { + "inputs": [], + "name": "NoSettlementProposedOrTransactionMovedOnAcceptSettlement", + "type": "error" + }, + { + "inputs": [], + "name": "NoSettlementProposedOrTransactionMovedOnPayFeeBuyer", + "type": "error" + }, + { + "inputs": [], + "name": "NoSettlementProposedOrTransactionMovedOnPayFeeSeller", + "type": "error" + }, + { + "inputs": [], + "name": "NotSupported", + "type": "error" + }, + { + "inputs": [], + "name": "NotWaitingForBuyerFees", + "type": "error" + }, + { + "inputs": [], + "name": "NotWaitingForSellerFees", + "type": "error" + }, + { + "inputs": [], + "name": "SellerFeeNotCoverArbitrationCosts", + "type": "error" + }, + { + "inputs": [], + "name": "SellerOnly", + "type": "error" + }, + { + "inputs": [], + "name": "SettlementPeriodNotOver", + "type": "error" + }, + { + "inputs": [], + "name": "TimeoutNotPassed", + "type": "error" + }, + { + "inputs": [], + "name": "TokenTransferFailed", + "type": "error" + }, + { + "inputs": [], + "name": "TransactionDisputed", + "type": "error" + }, + { + "inputs": [], + "name": "TransactionEscalatedForArbitration", + "type": "error" + }, + { + "inputs": [], + "name": "TransactionExpired", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract IArbitratorV2", + "name": "_arbitrator", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "_arbitratorDisputeID", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_externalDisputeID", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_templateId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "_templateUri", + "type": "string" + } + ], + "name": "DisputeRequest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "_transactionID", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "_transactionUri", + "type": "string" + }, + { + "indexed": true, + "internalType": "address", + "name": "_buyer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "_seller", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract IERC20", + "name": "_token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_deadline", + "type": "uint256" + } + ], + "name": "ERC20TransactionCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "_transactionID", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "enum Party", + "name": "_party", + "type": "uint8" + } + ], + "name": "HasToPayFee", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "_transactionID", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "_transactionUri", + "type": "string" + }, + { + "indexed": true, + "internalType": "address", + "name": "_buyer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "_seller", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_deadline", + "type": "uint256" + } + ], + "name": "NativeTransactionCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "_feeTimeout", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_settlementTimeout", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "_arbitratorExtraData", + "type": "bytes" + } + ], + "name": "ParameterUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "_transactionID", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "_party", + "type": "address" + } + ], + "name": "Payment", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract IArbitratorV2", + "name": "_arbitrator", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "_disputeID", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_ruling", + "type": "uint256" + } + ], + "name": "Ruling", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "_transactionID", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "enum Party", + "name": "_party", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "SettlementProposed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "_transactionID", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "enum Resolution", + "name": "_resolution", + "type": "uint8" + } + ], + "name": "TransactionResolved", + "type": "event" + }, + { + "inputs": [], + "name": "AMOUNT_OF_CHOICES", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_transactionID", + "type": "uint256" + } + ], + "name": "acceptSettlement", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "name": "amountCaps", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "arbitrator", + "outputs": [ + { + "internalType": "contract IArbitratorV2", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "arbitratorExtraData", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "_token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amountCap", + "type": "uint256" + } + ], + "name": "changeAmountCap", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IArbitratorV2", + "name": "_arbitrator", + "type": "address" + } + ], + "name": "changeArbitrator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "_arbitratorExtraData", + "type": "bytes" + } + ], + "name": "changeArbitratorExtraData", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_templateData", + "type": "string" + }, + { + "internalType": "string", + "name": "_templateDataMappings", + "type": "string" + } + ], + "name": "changeDisputeTemplate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_feeTimeout", + "type": "uint256" + } + ], + "name": "changeFeeTimeout", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_governor", + "type": "address" + } + ], + "name": "changeGovernor", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_settlementTimeout", + "type": "uint256" + } + ], + "name": "changeSettlementTimeout", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IDisputeTemplateRegistry", + "name": "_templateRegistry", + "type": "address" + } + ], + "name": "changeTemplateRegistry", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "internalType": "contract IERC20", + "name": "_token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_deadline", + "type": "uint256" + }, + { + "internalType": "string", + "name": "_transactionUri", + "type": "string" + }, + { + "internalType": "address payable", + "name": "_seller", + "type": "address" + } + ], + "name": "createERC20Transaction", + "outputs": [ + { + "internalType": "uint256", + "name": "transactionID", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "internalType": "contract IERC20", + "name": "_token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_deadline", + "type": "uint256" + }, + { + "internalType": "string", + "name": "_transactionUri", + "type": "string" + }, + { + "internalType": "address payable", + "name": "_buyer", + "type": "address" + }, + { + "internalType": "address payable", + "name": "_seller", + "type": "address" + } + ], + "name": "createERC20TransactionCustomBuyer", + "outputs": [ + { + "internalType": "uint256", + "name": "transactionID", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_deadline", + "type": "uint256" + }, + { + "internalType": "string", + "name": "_transactionUri", + "type": "string" + }, + { + "internalType": "address payable", + "name": "_seller", + "type": "address" + } + ], + "name": "createNativeTransaction", + "outputs": [ + { + "internalType": "uint256", + "name": "transactionID", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_deadline", + "type": "uint256" + }, + { + "internalType": "string", + "name": "_transactionUri", + "type": "string" + }, + { + "internalType": "address payable", + "name": "_buyer", + "type": "address" + }, + { + "internalType": "address payable", + "name": "_seller", + "type": "address" + } + ], + "name": "createNativeTransactionCustomBuyer", + "outputs": [ + { + "internalType": "uint256", + "name": "transactionID", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "disputeIDtoTransactionID", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_transactionID", + "type": "uint256" + } + ], + "name": "executeTransaction", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "feeTimeout", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_transactionID", + "type": "uint256" + }, + { + "internalType": "enum Party", + "name": "_winningParty", + "type": "uint8" + } + ], + "name": "getPayouts", + "outputs": [ + { + "internalType": "uint256", + "name": "buyerPayout", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "buyerPayoutToken", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "sellerPayout", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "sellerPayoutToken", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getTransactionCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "governor", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_transactionID", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "pay", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_transactionID", + "type": "uint256" + } + ], + "name": "payArbitrationFeeByBuyer", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_transactionID", + "type": "uint256" + } + ], + "name": "payArbitrationFeeBySeller", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_transactionID", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "proposeSettlement", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_transactionID", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_amountReimbursed", + "type": "uint256" + } + ], + "name": "reimburse", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_disputeID", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_ruling", + "type": "uint256" + } + ], + "name": "rule", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "settlementTimeout", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "templateId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "templateRegistry", + "outputs": [ + { + "internalType": "contract IDisputeTemplateRegistry", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_transactionID", + "type": "uint256" + } + ], + "name": "timeOutByBuyer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_transactionID", + "type": "uint256" + } + ], + "name": "timeOutBySeller", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "transactions", + "outputs": [ + { + "internalType": "address payable", + "name": "buyer", + "type": "address" + }, + { + "internalType": "address payable", + "name": "seller", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "settlementBuyer", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "settlementSeller", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "disputeID", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "buyerFee", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "sellerFee", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "lastFeePaymentTime", + "type": "uint256" + }, + { + "internalType": "enum Status", + "name": "status", + "type": "uint8" + }, + { + "internalType": "contract IERC20", + "name": "token", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0x5bdf3d51ed9eff9c0a9b239d779ade148b777355eb3a703026342c74840efe8d", + "receipt": { + "to": null, + "from": "0xf1C7c037891525E360C59f708739Ac09A7670c59", + "contractAddress": "0xA01e6B988aeDae1fD4a748D6bfBcB8A438601DeE", + "transactionIndex": 5, + "gasUsed": "2495336", + "logsBloom": "0x00000000000000000000000000000000000000000000000000040000000000008000080000000000000000000000000400001000000000000000001000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000080040000000000000000000000000000000080000000000002000000000000000000000000000000000000002000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000400000000000100000000000000000000000000000000080000", + "blockHash": "0x69e7d8ce5eef784d5cec9796e7286710cf5ee535aee8971a969dcdd88aabe113", + "transactionHash": "0x5bdf3d51ed9eff9c0a9b239d779ade148b777355eb3a703026342c74840efe8d", + "logs": [ + { + "transactionIndex": 5, + "blockNumber": 177253521, + "transactionHash": "0x5bdf3d51ed9eff9c0a9b239d779ade148b777355eb3a703026342c74840efe8d", + "address": "0xc852F94f90E3B06Da6eCfB61d76561ECfb94613f", + "topics": [ + "0x00f7cd7255d1073b4e136dd477c38ea0020c051ab17110cc5bfab0c840ff9924", + "0x0000000000000000000000000000000000000000000000000000000000000017", + "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470" + ], + "data": "0x0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "logIndex": 13, + "blockHash": "0x69e7d8ce5eef784d5cec9796e7286710cf5ee535aee8971a969dcdd88aabe113" + }, + { + "transactionIndex": 5, + "blockNumber": 177253521, + "transactionHash": "0x5bdf3d51ed9eff9c0a9b239d779ade148b777355eb3a703026342c74840efe8d", + "address": "0xA01e6B988aeDae1fD4a748D6bfBcB8A438601DeE", + "topics": [ + "0xf0d0a0b363c32316c3e6e7e797bbc126af09c634db439ed65a3f96afe7ae2367" + ], + "data": "0x000000000000000000000000000000000000000000000000000000000000025800000000000000000000000000000000000000000000000000000000000002580000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001", + "logIndex": 14, + "blockHash": "0x69e7d8ce5eef784d5cec9796e7286710cf5ee535aee8971a969dcdd88aabe113" + } + ], + "blockNumber": 177253521, + "cumulativeGasUsed": "2883768", + "status": 1, + "byzantium": true + }, + "args": [ + "0x1Bd44c4a4511DbFa7DC1d5BC201635596E7200f9", + "0x00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001", + "", + "", + "0xc852F94f90E3B06Da6eCfB61d76561ECfb94613f", + 600, + 600 + ], + "numDeployments": 1, + "solcInputHash": "fab05c4d500438ef529c26fabe219229", + "metadata": "{\"compiler\":{\"version\":\"0.8.24+commit.e11b9ed9\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IArbitratorV2\",\"name\":\"_arbitrator\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_arbitratorExtraData\",\"type\":\"bytes\"},{\"internalType\":\"string\",\"name\":\"_templateData\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"_templateDataMappings\",\"type\":\"string\"},{\"internalType\":\"contract IDisputeTemplateRegistry\",\"name\":\"_templateRegistry\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_feeTimeout\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_settlementTimeout\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"AmountExceedsCap\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ArbitratorOnly\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BuyerFeeNotCoverArbitrationCosts\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BuyerOnly\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BuyerOrSellerOnly\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DeadlineNotPassed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DisputeAlreadyResolved\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GovernorOnly\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRuling\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MaximumPaymentAmountExceeded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoSettlementProposedOrTransactionMovedOnAcceptSettlement\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoSettlementProposedOrTransactionMovedOnPayFeeBuyer\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoSettlementProposedOrTransactionMovedOnPayFeeSeller\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotSupported\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotWaitingForBuyerFees\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotWaitingForSellerFees\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SellerFeeNotCoverArbitrationCosts\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SellerOnly\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SettlementPeriodNotOver\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TimeoutNotPassed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TokenTransferFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TransactionDisputed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TransactionEscalatedForArbitration\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TransactionExpired\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IArbitratorV2\",\"name\":\"_arbitrator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"_arbitratorDisputeID\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_externalDisputeID\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_templateId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"_templateUri\",\"type\":\"string\"}],\"name\":\"DisputeRequest\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"_transactionID\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"_transactionUri\",\"type\":\"string\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_buyer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_seller\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"contract IERC20\",\"name\":\"_token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_deadline\",\"type\":\"uint256\"}],\"name\":\"ERC20TransactionCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"_transactionID\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"enum Party\",\"name\":\"_party\",\"type\":\"uint8\"}],\"name\":\"HasToPayFee\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"_transactionID\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"_transactionUri\",\"type\":\"string\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_buyer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_seller\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_deadline\",\"type\":\"uint256\"}],\"name\":\"NativeTransactionCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_feeTimeout\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_settlementTimeout\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"_arbitratorExtraData\",\"type\":\"bytes\"}],\"name\":\"ParameterUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"_transactionID\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_party\",\"type\":\"address\"}],\"name\":\"Payment\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IArbitratorV2\",\"name\":\"_arbitrator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"_disputeID\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_ruling\",\"type\":\"uint256\"}],\"name\":\"Ruling\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"_transactionID\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"enum Party\",\"name\":\"_party\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"SettlementProposed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"_transactionID\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"enum Resolution\",\"name\":\"_resolution\",\"type\":\"uint8\"}],\"name\":\"TransactionResolved\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"AMOUNT_OF_CHOICES\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_transactionID\",\"type\":\"uint256\"}],\"name\":\"acceptSettlement\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"amountCaps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"arbitrator\",\"outputs\":[{\"internalType\":\"contract IArbitratorV2\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"arbitratorExtraData\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amountCap\",\"type\":\"uint256\"}],\"name\":\"changeAmountCap\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IArbitratorV2\",\"name\":\"_arbitrator\",\"type\":\"address\"}],\"name\":\"changeArbitrator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_arbitratorExtraData\",\"type\":\"bytes\"}],\"name\":\"changeArbitratorExtraData\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_templateData\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"_templateDataMappings\",\"type\":\"string\"}],\"name\":\"changeDisputeTemplate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_feeTimeout\",\"type\":\"uint256\"}],\"name\":\"changeFeeTimeout\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_governor\",\"type\":\"address\"}],\"name\":\"changeGovernor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_settlementTimeout\",\"type\":\"uint256\"}],\"name\":\"changeSettlementTimeout\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IDisputeTemplateRegistry\",\"name\":\"_templateRegistry\",\"type\":\"address\"}],\"name\":\"changeTemplateRegistry\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_deadline\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"_transactionUri\",\"type\":\"string\"},{\"internalType\":\"address payable\",\"name\":\"_seller\",\"type\":\"address\"}],\"name\":\"createERC20Transaction\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"transactionID\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_deadline\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"_transactionUri\",\"type\":\"string\"},{\"internalType\":\"address payable\",\"name\":\"_buyer\",\"type\":\"address\"},{\"internalType\":\"address payable\",\"name\":\"_seller\",\"type\":\"address\"}],\"name\":\"createERC20TransactionCustomBuyer\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"transactionID\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_deadline\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"_transactionUri\",\"type\":\"string\"},{\"internalType\":\"address payable\",\"name\":\"_seller\",\"type\":\"address\"}],\"name\":\"createNativeTransaction\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"transactionID\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_deadline\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"_transactionUri\",\"type\":\"string\"},{\"internalType\":\"address payable\",\"name\":\"_buyer\",\"type\":\"address\"},{\"internalType\":\"address payable\",\"name\":\"_seller\",\"type\":\"address\"}],\"name\":\"createNativeTransactionCustomBuyer\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"transactionID\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"disputeIDtoTransactionID\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_transactionID\",\"type\":\"uint256\"}],\"name\":\"executeTransaction\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"feeTimeout\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_transactionID\",\"type\":\"uint256\"},{\"internalType\":\"enum Party\",\"name\":\"_winningParty\",\"type\":\"uint8\"}],\"name\":\"getPayouts\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"buyerPayout\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"buyerPayoutToken\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"sellerPayout\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"sellerPayoutToken\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTransactionCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"governor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_transactionID\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"pay\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_transactionID\",\"type\":\"uint256\"}],\"name\":\"payArbitrationFeeByBuyer\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_transactionID\",\"type\":\"uint256\"}],\"name\":\"payArbitrationFeeBySeller\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_transactionID\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"proposeSettlement\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_transactionID\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_amountReimbursed\",\"type\":\"uint256\"}],\"name\":\"reimburse\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_disputeID\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_ruling\",\"type\":\"uint256\"}],\"name\":\"rule\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"settlementTimeout\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"templateId\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"templateRegistry\",\"outputs\":[{\"internalType\":\"contract IDisputeTemplateRegistry\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_transactionID\",\"type\":\"uint256\"}],\"name\":\"timeOutByBuyer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_transactionID\",\"type\":\"uint256\"}],\"name\":\"timeOutBySeller\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"transactions\",\"outputs\":[{\"internalType\":\"address payable\",\"name\":\"buyer\",\"type\":\"address\"},{\"internalType\":\"address payable\",\"name\":\"seller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"settlementBuyer\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"settlementSeller\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"disputeID\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"buyerFee\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"sellerFee\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"lastFeePaymentTime\",\"type\":\"uint256\"},{\"internalType\":\"enum Status\",\"name\":\"status\",\"type\":\"uint8\"},{\"internalType\":\"contract IERC20\",\"name\":\"token\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Version of Escrow that allows to specify a buyer when transaction is created.\",\"events\":{\"DisputeRequest(address,uint256,uint256,uint256,string)\":{\"details\":\"To be emitted when a dispute is created to link the correct meta-evidence to the disputeID.\",\"params\":{\"_arbitrator\":\"The arbitrator of the contract.\",\"_arbitratorDisputeID\":\"The identifier of the dispute in the Arbitrator contract.\",\"_externalDisputeID\":\"An identifier created outside Kleros by the protocol requesting arbitration.\",\"_templateId\":\"The identifier of the dispute template. Should not be used with _templateUri.\",\"_templateUri\":\"The URI to the dispute template. For example on IPFS: starting with '/ipfs/'. Should not be used with _templateId.\"}},\"ERC20TransactionCreated(uint256,string,address,address,address,uint256,uint256)\":{\"details\":\"Emitted when a transaction paid in ERC20 token is created.\",\"params\":{\"_amount\":\"The initial amount in the transaction.\",\"_buyer\":\"The address of the buyer.\",\"_deadline\":\"The deadline of the transaction.\",\"_seller\":\"The address of the seller.\",\"_token\":\"The token address.\",\"_transactionID\":\"The index of the transaction.\",\"_transactionUri\":\"The IPFS Uri Hash of the transaction.\"}},\"HasToPayFee(uint256,uint8)\":{\"details\":\"Indicate that a party has to pay a fee or would otherwise be considered as losing.\",\"params\":{\"_party\":\"The party who has to pay.\",\"_transactionID\":\"The index of the transaction.\"}},\"NativeTransactionCreated(uint256,string,address,address,uint256,uint256)\":{\"details\":\"Emitted when a transaction paid in native currency is created.\",\"params\":{\"_amount\":\"The initial amount in the transaction.\",\"_buyer\":\"The address of the buyer.\",\"_deadline\":\"The deadline of the transaction.\",\"_seller\":\"The address of the seller.\",\"_transactionID\":\"The index of the transaction.\",\"_transactionUri\":\"The IPFS Uri Hash of the transaction.\"}},\"ParameterUpdated(uint256,uint256,bytes)\":{\"details\":\"To be emitted when Escrow parameters are updated.\"},\"Payment(uint256,uint256,address)\":{\"details\":\"To be emitted when a party pays or reimburses the other.\",\"params\":{\"_amount\":\"The amount paid.\",\"_party\":\"The party that paid.\",\"_transactionID\":\"The index of the transaction.\"}},\"Ruling(address,uint256,uint256)\":{\"details\":\"To be raised when a ruling is given.\",\"params\":{\"_arbitrator\":\"The arbitrator giving the ruling.\",\"_disputeID\":\"The identifier of the dispute in the Arbitrator contract.\",\"_ruling\":\"The ruling which was given.\"}},\"SettlementProposed(uint256,uint8,uint256)\":{\"details\":\"Emitted when a party proposes a settlement.\",\"params\":{\"_amount\":\"The amount proposed.\",\"_party\":\"The party that proposed a settlement.\",\"_transactionID\":\"The index of the transaction.\"}},\"TransactionResolved(uint256,uint8)\":{\"details\":\"To be emitted when a transaction is resolved, either by its execution, a timeout or because a ruling was enforced.\",\"params\":{\"_resolution\":\"Short description of what caused the transaction to be solved.\",\"_transactionID\":\"The ID of the respective transaction.\"}}},\"kind\":\"dev\",\"methods\":{\"acceptSettlement(uint256)\":{\"details\":\"Accept a settlement proposed by the other party.\",\"params\":{\"_transactionID\":\"The index of the transaction.\"}},\"constructor\":{\"details\":\"Constructor.\",\"params\":{\"_arbitrator\":\"The arbitrator of the contract.\",\"_arbitratorExtraData\":\"Extra data for the arbitrator.\",\"_feeTimeout\":\"Arbitration fee timeout for the parties.\",\"_settlementTimeout\":\"Settlement timeout for the parties.\",\"_templateData\":\"The dispute template data.\",\"_templateDataMappings\":\"The dispute template data mappings.\",\"_templateRegistry\":\"The dispute template registry.\"}},\"createERC20Transaction(uint256,address,uint256,string,address)\":{\"details\":\"Create a transaction.\",\"params\":{\"_amount\":\"The amount of tokens in this transaction.\",\"_deadline\":\"Time after which a party can automatically execute the arbitrable transaction.\",\"_seller\":\"The recipient of the transaction.\",\"_token\":\"The ERC20 token contract.\",\"_transactionUri\":\"The IPFS Uri Hash of the transaction.\"},\"returns\":{\"transactionID\":\"The index of the transaction.\"}},\"createERC20TransactionCustomBuyer(uint256,address,uint256,string,address,address)\":{\"details\":\"Create an ERC20 transaction with custom buyer address.\",\"params\":{\"_amount\":\"The amount of tokens in this transaction.\",\"_buyer\":\"Buyer's address.\",\"_deadline\":\"Time after which a party can automatically execute the arbitrable transaction.\",\"_seller\":\"The recipient of the transaction.\",\"_token\":\"The ERC20 token contract.\",\"_transactionUri\":\"The IPFS Uri Hash of the transaction.\"},\"returns\":{\"transactionID\":\"The index of the transaction.\"}},\"createNativeTransaction(uint256,string,address)\":{\"details\":\"Create a transaction.\",\"params\":{\"_deadline\":\"Time after which a party can automatically execute the arbitrable transaction.\",\"_seller\":\"The recipient of the transaction.\",\"_transactionUri\":\"The IPFS Uri Hash of the transaction.\"},\"returns\":{\"transactionID\":\"The index of the transaction.\"}},\"createNativeTransactionCustomBuyer(uint256,string,address,address)\":{\"details\":\"Create a native transaction with custom buyer.\",\"params\":{\"_buyer\":\"Buyer's address.\",\"_deadline\":\"Time after which a party can automatically execute the arbitrable transaction.\",\"_seller\":\"The recipient of the transaction.\",\"_transactionUri\":\"The IPFS Uri Hash of the transaction.\"},\"returns\":{\"transactionID\":\"The index of the transaction.\"}},\"executeTransaction(uint256)\":{\"details\":\"Transfer the transaction's amount to the seller if the timeout has passed.\",\"params\":{\"_transactionID\":\"The index of the transaction.\"}},\"getPayouts(uint256,uint8)\":{\"details\":\"Get the payout depending on the winning party.The cost for the buyer is the seller payout non-inclusive of any arbitration fees.\",\"params\":{\"_transactionID\":\"The index of the transaction.\",\"_winningParty\":\"The winning party.\"},\"returns\":{\"buyerPayout\":\"The payout for the buyer.\",\"buyerPayoutToken\":\"The payout for the buyer in tokens.\",\"sellerPayout\":\"The payout for the seller.\",\"sellerPayoutToken\":\"The payout for the seller in tokens.\"}},\"getTransactionCount()\":{\"details\":\"Getter to know the count of transactions.\",\"returns\":{\"_0\":\"The count of transactions.\"}},\"pay(uint256,uint256)\":{\"details\":\"Pay seller. To be called if the good or service is provided.\",\"params\":{\"_amount\":\"Amount to pay in wei.\",\"_transactionID\":\"The index of the transaction.\"}},\"payArbitrationFeeByBuyer(uint256)\":{\"details\":\"Pay the arbitration fee to raise a dispute. To be called by the buyer. Note that it can only be called after settlement proposition. Also note that the arbitrator can have createDispute throw, which will make this function throw and therefore lead to a party being timed-out. This is not a vulnerability as the arbitrator can rule in favor of one party anyway.\",\"params\":{\"_transactionID\":\"The index of the transaction.\"}},\"payArbitrationFeeBySeller(uint256)\":{\"details\":\"Pay the arbitration fee to raise a dispute. To be called by the seller. Note that this function mirrors payArbitrationFeeByBuyer.\",\"params\":{\"_transactionID\":\"The index of the transaction.\"}},\"proposeSettlement(uint256,uint256)\":{\"details\":\"Propose a settlement as a compromise from the initial terms to the other party. Note that a party can only propose a settlement again after the other party has done so as well to prevent front running/griefing issues.\",\"params\":{\"_amount\":\"The settlement amount.\",\"_transactionID\":\"The index of the transaction.\"}},\"reimburse(uint256,uint256)\":{\"details\":\"Reimburse buyer. To be called if the good or service can't be fully provided.\",\"params\":{\"_amountReimbursed\":\"Amount to reimburse in wei.\",\"_transactionID\":\"The index of the transaction.\"}},\"rule(uint256,uint256)\":{\"details\":\"Give a ruling for a dispute. Must be called by the arbitrator. The purpose of this function is to ensure that the address calling it has the right to rule on the contract.\",\"params\":{\"_disputeID\":\"The identifier of the dispute in the Arbitrator contract.\",\"_ruling\":\"Ruling given by the arbitrator. Note that 0 is reserved for \\\"Not able/wanting to make a decision\\\".\"}},\"timeOutByBuyer(uint256)\":{\"details\":\"Reimburse buyer if seller fails to pay the fee.\",\"params\":{\"_transactionID\":\"The index of the transaction.\"}},\"timeOutBySeller(uint256)\":{\"details\":\"Pay seller if buyer fails to pay the fee.\",\"params\":{\"_transactionID\":\"The index of the transaction.\"}}},\"title\":\"EscrowCustomBuyer.\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/EscrowCustomBuyer.sol\":\"EscrowCustomBuyer\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":100},\"remappings\":[],\"viaIR\":true},\"sources\":{\"@kleros/kleros-v2-contracts/arbitration/interfaces/IArbitrableV2.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.24;\\n\\nimport \\\"./IArbitratorV2.sol\\\";\\n\\n/// @title IArbitrableV2\\n/// @notice Arbitrable interface.\\n/// @dev When developing arbitrable contracts, we need to:\\n/// - Define the action taken when a ruling is received by the contract.\\n/// - Allow dispute creation. For this a function must call arbitrator.createDispute{value: _fee}(_choices,_extraData);\\ninterface IArbitrableV2 {\\n /// @dev To be emitted when a dispute is created to link the correct meta-evidence to the disputeID.\\n /// @param _arbitrator The arbitrator of the contract.\\n /// @param _arbitratorDisputeID The identifier of the dispute in the Arbitrator contract.\\n /// @param _externalDisputeID An identifier created outside Kleros by the protocol requesting arbitration.\\n /// @param _templateId The identifier of the dispute template. Should not be used with _templateUri.\\n /// @param _templateUri The URI to the dispute template. For example on IPFS: starting with '/ipfs/'. Should not be used with _templateId.\\n event DisputeRequest(\\n IArbitratorV2 indexed _arbitrator,\\n uint256 indexed _arbitratorDisputeID,\\n uint256 _externalDisputeID,\\n uint256 _templateId,\\n string _templateUri\\n );\\n\\n /// @dev To be raised when a ruling is given.\\n /// @param _arbitrator The arbitrator giving the ruling.\\n /// @param _disputeID The identifier of the dispute in the Arbitrator contract.\\n /// @param _ruling The ruling which was given.\\n event Ruling(IArbitratorV2 indexed _arbitrator, uint256 indexed _disputeID, uint256 _ruling);\\n\\n /// @dev Give a ruling for a dispute.\\n /// Must be called by the arbitrator.\\n /// The purpose of this function is to ensure that the address calling it has the right to rule on the contract.\\n /// @param _disputeID The identifier of the dispute in the Arbitrator contract.\\n /// @param _ruling Ruling given by the arbitrator.\\n /// Note that 0 is reserved for \\\"Not able/wanting to make a decision\\\".\\n function rule(uint256 _disputeID, uint256 _ruling) external;\\n}\\n\",\"keccak256\":\"0x054fd09cc201ddca3d92a07169fb86b9db21a510a2a0f15ac4b6dffd900079fe\",\"license\":\"MIT\"},\"@kleros/kleros-v2-contracts/arbitration/interfaces/IArbitratorV2.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.24;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"./IArbitrableV2.sol\\\";\\n\\n/// @title Arbitrator\\n/// Arbitrator interface that implements the new arbitration standard.\\n/// Unlike the ERC-792 this standard is not concerned with appeals, so each arbitrator can implement an appeal system that suits it the most.\\n/// When developing arbitrator contracts we need to:\\n/// - Define the functions for dispute creation (createDispute). Don't forget to store the arbitrated contract and the disputeID (which should be unique, may nbDisputes).\\n/// - Define the functions for cost display (arbitrationCost).\\n/// - Allow giving rulings. For this a function must call arbitrable.rule(disputeID, ruling).\\ninterface IArbitratorV2 {\\n /// @dev To be emitted when a dispute is created.\\n /// @param _disputeID The identifier of the dispute in the Arbitrator contract.\\n /// @param _arbitrable The contract which created the dispute.\\n event DisputeCreation(uint256 indexed _disputeID, IArbitrableV2 indexed _arbitrable);\\n\\n /// @dev To be raised when a ruling is given.\\n /// @param _arbitrable The arbitrable receiving the ruling.\\n /// @param _disputeID The identifier of the dispute in the Arbitrator contract.\\n /// @param _ruling The ruling which was given.\\n event Ruling(IArbitrableV2 indexed _arbitrable, uint256 indexed _disputeID, uint256 _ruling);\\n\\n /// @dev To be emitted when an ERC20 token is added or removed as a method to pay fees.\\n /// @param _token The ERC20 token.\\n /// @param _accepted Whether the token is accepted or not.\\n event AcceptedFeeToken(IERC20 indexed _token, bool indexed _accepted);\\n\\n /// @dev To be emitted when the fee for a particular ERC20 token is updated.\\n /// @param _feeToken The ERC20 token.\\n /// @param _rateInEth The new rate of the fee token in ETH.\\n /// @param _rateDecimals The new decimals of the fee token rate.\\n event NewCurrencyRate(IERC20 indexed _feeToken, uint64 _rateInEth, uint8 _rateDecimals);\\n\\n /// @dev Create a dispute and pay for the fees in the native currency, typically ETH.\\n /// Must be called by the arbitrable contract.\\n /// Must pay at least arbitrationCost(_extraData).\\n /// @param _numberOfChoices The number of choices the arbitrator can choose from in this dispute.\\n /// @param _extraData Additional info about the dispute. We use it to pass the ID of the dispute's court (first 32 bytes), the minimum number of jurors required (next 32 bytes) and the ID of the specific dispute kit (last 32 bytes).\\n /// @return disputeID The identifier of the dispute created.\\n function createDispute(\\n uint256 _numberOfChoices,\\n bytes calldata _extraData\\n ) external payable returns (uint256 disputeID);\\n\\n /// @dev Create a dispute and pay for the fees in a supported ERC20 token.\\n /// Must be called by the arbitrable contract.\\n /// Must pay at least arbitrationCost(_extraData).\\n /// @param _numberOfChoices The number of choices the arbitrator can choose from in this dispute.\\n /// @param _extraData Additional info about the dispute. We use it to pass the ID of the dispute's court (first 32 bytes), the minimum number of jurors required (next 32 bytes) and the ID of the specific dispute kit (last 32 bytes).\\n /// @param _feeToken The ERC20 token used to pay fees.\\n /// @param _feeAmount Amount of the ERC20 token used to pay fees.\\n /// @return disputeID The identifier of the dispute created.\\n function createDispute(\\n uint256 _numberOfChoices,\\n bytes calldata _extraData,\\n IERC20 _feeToken,\\n uint256 _feeAmount\\n ) external returns (uint256 disputeID);\\n\\n /// @dev Compute the cost of arbitration denominated in the native currency, typically ETH.\\n /// It is recommended not to increase it often, as it can be highly time and gas consuming for the arbitrated contracts to cope with fee augmentation.\\n /// @param _extraData Additional info about the dispute. We use it to pass the ID of the dispute's court (first 32 bytes), the minimum number of jurors required (next 32 bytes) and the ID of the specific dispute kit (last 32 bytes).\\n /// @return cost The arbitration cost in ETH.\\n function arbitrationCost(bytes calldata _extraData) external view returns (uint256 cost);\\n\\n /// @dev Compute the cost of arbitration denominated in `_feeToken`.\\n /// It is recommended not to increase it often, as it can be highly time and gas consuming for the arbitrated contracts to cope with fee augmentation.\\n /// @param _extraData Additional info about the dispute. We use it to pass the ID of the dispute's court (first 32 bytes), the minimum number of jurors required (next 32 bytes) and the ID of the specific dispute kit (last 32 bytes).\\n /// @param _feeToken The ERC20 token used to pay fees.\\n /// @return cost The arbitration cost in `_feeToken`.\\n function arbitrationCost(bytes calldata _extraData, IERC20 _feeToken) external view returns (uint256 cost);\\n\\n /// @dev Gets the current ruling of a specified dispute.\\n /// @param _disputeID The ID of the dispute.\\n /// @return ruling The current ruling.\\n /// @return tied Whether it's a tie or not.\\n /// @return overridden Whether the ruling was overridden by appeal funding or not.\\n function currentRuling(uint256 _disputeID) external view returns (uint256 ruling, bool tied, bool overridden);\\n}\\n\",\"keccak256\":\"0xfc7cc82c1431720da41aeb1a181171f10466b5d0d280db7aa37c451681185493\",\"license\":\"MIT\"},\"@kleros/kleros-v2-contracts/arbitration/interfaces/IDisputeTemplateRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.24;\\n\\n/// @title IDisputeTemplate\\n/// @notice Dispute Template interface.\\ninterface IDisputeTemplateRegistry {\\n /// @dev To be emitted when a new dispute template is created.\\n /// @param _templateId The identifier of the dispute template.\\n /// @param _templateTag An optional tag for the dispute template, such as \\\"registration\\\" or \\\"removal\\\".\\n /// @param _templateData The template data.\\n /// @param _templateDataMappings The data mappings.\\n event DisputeTemplate(\\n uint256 indexed _templateId,\\n string indexed _templateTag,\\n string _templateData,\\n string _templateDataMappings\\n );\\n\\n function setDisputeTemplate(\\n string memory _templateTag,\\n string memory _templateData,\\n string memory _templateDataMappings\\n ) external returns (uint256 templateId);\\n}\\n\",\"keccak256\":\"0xd8122941175d1d5c2983e71717a2fdcc6fe94aa9de08f87eb7c44e3a5f1c2030\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Interface of the ERC-20 standard as defined in the ERC.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the value of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the value of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 value) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\\n * caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 value) external returns (bool);\\n\\n /**\\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\\n * allowance mechanism. `value` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 value) external returns (bool);\\n}\\n\",\"keccak256\":\"0xe06a3f08a987af6ad2e1c1e774405d4fe08f1694b67517438b467cecf0da0ef7\",\"license\":\"MIT\"},\"src/EscrowCustomBuyer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\n/// @authors: [@unknownunknown1, @jaybuidl]\\n/// @reviewers: []\\n/// @auditors: []\\n/// @bounties: []\\n\\npragma solidity 0.8.24;\\n\\nimport {EscrowUniversal, SafeERC20, IERC20, IArbitratorV2, IDisputeTemplateRegistry, NATIVE, Transaction} from \\\"./EscrowUniversal.sol\\\";\\n\\n/// @title EscrowCustomBuyer.\\n/// @dev Version of Escrow that allows to specify a buyer when transaction is created.\\ncontract EscrowCustomBuyer is EscrowUniversal {\\n using SafeERC20 for IERC20;\\n\\n /// @dev Constructor.\\n /// @param _arbitrator The arbitrator of the contract.\\n /// @param _arbitratorExtraData Extra data for the arbitrator.\\n /// @param _templateData The dispute template data.\\n /// @param _templateDataMappings The dispute template data mappings.\\n /// @param _templateRegistry The dispute template registry.\\n /// @param _feeTimeout Arbitration fee timeout for the parties.\\n /// @param _settlementTimeout Settlement timeout for the parties.\\n constructor(\\n IArbitratorV2 _arbitrator,\\n bytes memory _arbitratorExtraData,\\n string memory _templateData,\\n string memory _templateDataMappings,\\n IDisputeTemplateRegistry _templateRegistry,\\n uint256 _feeTimeout,\\n uint256 _settlementTimeout\\n )\\n EscrowUniversal(\\n _arbitrator,\\n _arbitratorExtraData,\\n _templateData,\\n _templateDataMappings,\\n _templateRegistry,\\n _feeTimeout,\\n _settlementTimeout\\n )\\n {}\\n\\n /// @dev Create a native transaction with custom buyer.\\n /// @param _deadline Time after which a party can automatically execute the arbitrable transaction.\\n /// @param _transactionUri The IPFS Uri Hash of the transaction.\\n /// @param _buyer Buyer's address.\\n /// @param _seller The recipient of the transaction.\\n /// @return transactionID The index of the transaction.\\n function createNativeTransactionCustomBuyer(\\n uint256 _deadline,\\n string memory _transactionUri,\\n address payable _buyer,\\n address payable _seller\\n ) external payable shouldNotExceedCap(NATIVE, msg.value) returns (uint256 transactionID) {\\n Transaction storage transaction = transactions.push();\\n transaction.buyer = _buyer;\\n transaction.seller = _seller;\\n /// Note that in this version of the contract the amount is provided by the caller, not by the buyer.\\n transaction.amount = msg.value;\\n transaction.token = NATIVE;\\n transaction.deadline = _deadline;\\n\\n transactionID = transactions.length - 1;\\n\\n emit NativeTransactionCreated(transactionID, _transactionUri, _buyer, _seller, msg.value, transaction.deadline);\\n }\\n\\n /// @dev Create an ERC20 transaction with custom buyer address.\\n /// @param _amount The amount of tokens in this transaction.\\n /// @param _token The ERC20 token contract.\\n /// @param _deadline Time after which a party can automatically execute the arbitrable transaction.\\n /// @param _transactionUri The IPFS Uri Hash of the transaction.\\n /// @param _buyer Buyer's address.\\n /// @param _seller The recipient of the transaction.\\n /// @return transactionID The index of the transaction.\\n function createERC20TransactionCustomBuyer(\\n uint256 _amount,\\n IERC20 _token,\\n uint256 _deadline,\\n string memory _transactionUri,\\n address payable _buyer,\\n address payable _seller\\n ) external shouldNotExceedCap(_token, _amount) returns (uint256 transactionID) {\\n // Transfers token from sender wallet to contract. Note that in this version of the contract the amount is provided by the caller, not by the buyer.\\n if (!_token.safeTransferFrom(msg.sender, address(this), _amount)) revert TokenTransferFailed();\\n Transaction storage transaction = transactions.push();\\n transaction.buyer = _buyer;\\n transaction.seller = _seller;\\n transaction.amount = _amount;\\n transaction.token = _token;\\n transaction.deadline = _deadline;\\n\\n transactionID = transactions.length - 1;\\n\\n emit ERC20TransactionCreated(\\n transactionID,\\n _transactionUri,\\n _buyer,\\n _seller,\\n _token,\\n _amount,\\n transaction.deadline\\n );\\n }\\n}\\n\",\"keccak256\":\"0x8ef448221eb93f2f9b1f0ba30b964614c79505fc0abcecb3a2d9c974ce6d4590\",\"license\":\"MIT\"},\"src/EscrowUniversal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\n/// @authors: [@unknownunknown1, @jaybuidl]\\n/// @reviewers: []\\n/// @auditors: []\\n/// @bounties: []\\n\\npragma solidity 0.8.24;\\n\\nimport {IArbitrableV2, IArbitratorV2} from \\\"@kleros/kleros-v2-contracts/arbitration/interfaces/IArbitrableV2.sol\\\";\\nimport \\\"@kleros/kleros-v2-contracts/arbitration/interfaces/IDisputeTemplateRegistry.sol\\\";\\nimport {SafeERC20, IERC20} from \\\"./libraries/SafeERC20.sol\\\";\\nimport \\\"./interfaces/IEscrow.sol\\\";\\n\\n/// @title EscrowUniversal for a sale paid in native currency or ERC20 tokens without platform fees.\\n/// @dev Adapted from MultipleArbitrableTokenTransaction contract: https://github.com/kleros/kleros-interaction/blob/master/contracts/standard/arbitration/MultipleArbitrableTokenTransaction.sol\\n/// and from MultipleArbitrableTransaction contract: https://github.com/kleros/kleros-interaction/blob/master/contracts/standard/arbitration/MultipleArbitrableTransaction.sol\\n/// Note that the contract expects the tokens to have standard ERC20 behaviour.\\n/// The tokens that don't conform to this type of behaviour should be filtered by the UI.\\n/// Tokens should not reenter or allow recipients to refuse the transfer.\\n/// Also note that arbitration fees are still paid in ETH.\\ncontract EscrowUniversal is IEscrow, IArbitrableV2 {\\n // Use safe transfers when both parties are paid simultaneously (save for acceptSettlement) to prevent griefing.\\n using SafeERC20 for IERC20;\\n\\n // ************************************* //\\n // * Storage * //\\n // ************************************* //\\n\\n uint256 public constant AMOUNT_OF_CHOICES = 2;\\n address public governor;\\n IArbitratorV2 public arbitrator; // Address of the arbitrator contract.\\n bytes public arbitratorExtraData; // Extra data to set up the arbitration.\\n IDisputeTemplateRegistry public templateRegistry; // The dispute template registry.\\n uint256 public templateId; // The current dispute template identifier.\\n uint256 public feeTimeout; // Time in seconds a party can take to pay arbitration fees before being considered unresponsive and lose the dispute.\\n uint256 public settlementTimeout; // Time in seconds a party can take to accept or propose a settlement before being considered unresponsive.\\n Transaction[] public transactions; // List of all created transactions.\\n mapping(uint256 => uint256) public disputeIDtoTransactionID; // Naps dispute ID to tx ID.\\n mapping(IERC20 => uint256) public amountCaps; // Caps the amount of the respective token for the Escrow transaction.\\n\\n // ************************************* //\\n // * Function Modifiers * //\\n // ************************************* //\\n\\n modifier onlyByGovernor() {\\n if (governor != msg.sender) revert GovernorOnly();\\n _;\\n }\\n\\n modifier shouldNotExceedCap(IERC20 _token, uint256 _amount) {\\n if (_amount > amountCaps[_token]) revert AmountExceedsCap();\\n _;\\n }\\n\\n // ************************************* //\\n // * Constructor * //\\n // ************************************* //\\n\\n /// @dev Constructor.\\n /// @param _arbitrator The arbitrator of the contract.\\n /// @param _arbitratorExtraData Extra data for the arbitrator.\\n /// @param _templateData The dispute template data.\\n /// @param _templateDataMappings The dispute template data mappings.\\n /// @param _templateRegistry The dispute template registry.\\n /// @param _feeTimeout Arbitration fee timeout for the parties.\\n /// @param _settlementTimeout Settlement timeout for the parties.\\n constructor(\\n IArbitratorV2 _arbitrator,\\n bytes memory _arbitratorExtraData,\\n string memory _templateData,\\n string memory _templateDataMappings,\\n IDisputeTemplateRegistry _templateRegistry,\\n uint256 _feeTimeout,\\n uint256 _settlementTimeout\\n ) {\\n governor = msg.sender;\\n arbitrator = _arbitrator;\\n arbitratorExtraData = _arbitratorExtraData;\\n templateRegistry = _templateRegistry;\\n feeTimeout = _feeTimeout;\\n settlementTimeout = _settlementTimeout;\\n templateId = templateRegistry.setDisputeTemplate(\\\"\\\", _templateData, _templateDataMappings);\\n\\n emit ParameterUpdated(_feeTimeout, _settlementTimeout, _arbitratorExtraData);\\n }\\n\\n // ************************************* //\\n // * Governance * //\\n // ************************************* //\\n\\n function changeGovernor(address _governor) external onlyByGovernor {\\n governor = _governor;\\n }\\n\\n function changeArbitrator(IArbitratorV2 _arbitrator) external onlyByGovernor {\\n arbitrator = _arbitrator;\\n }\\n\\n function changeArbitratorExtraData(bytes calldata _arbitratorExtraData) external onlyByGovernor {\\n arbitratorExtraData = _arbitratorExtraData;\\n emit ParameterUpdated(feeTimeout, settlementTimeout, _arbitratorExtraData);\\n }\\n\\n function changeTemplateRegistry(IDisputeTemplateRegistry _templateRegistry) external onlyByGovernor {\\n templateRegistry = _templateRegistry;\\n }\\n\\n function changeDisputeTemplate(\\n string memory _templateData,\\n string memory _templateDataMappings\\n ) external onlyByGovernor {\\n templateId = templateRegistry.setDisputeTemplate(\\\"\\\", _templateData, _templateDataMappings);\\n }\\n\\n function changeFeeTimeout(uint256 _feeTimeout) external onlyByGovernor {\\n feeTimeout = _feeTimeout;\\n emit ParameterUpdated(_feeTimeout, settlementTimeout, arbitratorExtraData);\\n }\\n\\n function changeSettlementTimeout(uint256 _settlementTimeout) external onlyByGovernor {\\n settlementTimeout = _settlementTimeout;\\n emit ParameterUpdated(feeTimeout, _settlementTimeout, arbitratorExtraData);\\n }\\n\\n function changeAmountCap(IERC20 _token, uint256 _amountCap) external onlyByGovernor {\\n amountCaps[_token] = _amountCap;\\n }\\n\\n // ************************************* //\\n // * State Modifiers * //\\n // ************************************* //\\n\\n /// @inheritdoc IEscrow\\n function createNativeTransaction(\\n uint256 _deadline,\\n string memory _transactionUri,\\n address payable _seller\\n ) external payable override shouldNotExceedCap(NATIVE, msg.value) returns (uint256 transactionID) {\\n Transaction storage transaction = transactions.push();\\n transaction.buyer = payable(msg.sender);\\n transaction.seller = _seller;\\n transaction.amount = msg.value;\\n transaction.token = NATIVE;\\n transaction.deadline = _deadline;\\n\\n transactionID = transactions.length - 1;\\n\\n emit NativeTransactionCreated(\\n transactionID,\\n _transactionUri,\\n msg.sender,\\n _seller,\\n msg.value,\\n transaction.deadline\\n );\\n }\\n\\n /// @inheritdoc IEscrow\\n function createERC20Transaction(\\n uint256 _amount,\\n IERC20 _token,\\n uint256 _deadline,\\n string memory _transactionUri,\\n address payable _seller\\n ) external override shouldNotExceedCap(_token, _amount) returns (uint256 transactionID) {\\n // Transfers token from sender wallet to contract.\\n if (!_token.safeTransferFrom(msg.sender, address(this), _amount)) revert TokenTransferFailed();\\n Transaction storage transaction = transactions.push();\\n transaction.buyer = payable(msg.sender);\\n transaction.seller = _seller;\\n transaction.amount = _amount;\\n transaction.token = _token;\\n transaction.deadline = _deadline;\\n\\n transactionID = transactions.length - 1;\\n\\n emit ERC20TransactionCreated(\\n transactionID,\\n _transactionUri,\\n msg.sender,\\n _seller,\\n _token,\\n _amount,\\n transaction.deadline\\n );\\n }\\n\\n /// @inheritdoc IEscrow\\n function pay(uint256 _transactionID, uint256 _amount) external override {\\n Transaction storage transaction = transactions[_transactionID];\\n if (transaction.buyer != msg.sender) revert BuyerOnly();\\n if (transaction.status != Status.NoDispute) revert TransactionDisputed();\\n if (_amount > transaction.amount) revert MaximumPaymentAmountExceeded();\\n\\n emit Payment(_transactionID, _amount, transaction.buyer);\\n\\n transaction.amount -= _amount;\\n if (transaction.amount == 0) {\\n transaction.status = Status.TransactionResolved;\\n emit TransactionResolved(_transactionID, Resolution.TransactionExecuted);\\n }\\n\\n if (transaction.token == NATIVE) {\\n transaction.seller.send(_amount); // It is the user responsibility to accept ETH.\\n } else {\\n if (!transaction.token.safeTransfer(transaction.seller, _amount)) revert TokenTransferFailed();\\n }\\n }\\n\\n /// @inheritdoc IEscrow\\n function reimburse(uint256 _transactionID, uint256 _amountReimbursed) external override {\\n Transaction storage transaction = transactions[_transactionID];\\n if (transaction.seller != msg.sender) revert SellerOnly();\\n if (transaction.status != Status.NoDispute) revert TransactionDisputed();\\n if (_amountReimbursed > transaction.amount) revert MaximumPaymentAmountExceeded();\\n\\n emit Payment(_transactionID, _amountReimbursed, transaction.seller);\\n\\n transaction.amount -= _amountReimbursed;\\n if (transaction.amount == 0) {\\n transaction.status = Status.TransactionResolved;\\n emit TransactionResolved(_transactionID, Resolution.TransactionExecuted);\\n }\\n\\n if (transaction.token == NATIVE) {\\n transaction.buyer.send(_amountReimbursed); // It is the user responsibility to accept ETH.\\n } else {\\n if (!transaction.token.safeTransfer(transaction.buyer, _amountReimbursed)) revert TokenTransferFailed();\\n }\\n }\\n\\n /// @inheritdoc IEscrow\\n function executeTransaction(uint256 _transactionID) external override {\\n Transaction storage transaction = transactions[_transactionID];\\n if (block.timestamp < transaction.deadline) revert DeadlineNotPassed();\\n if (transaction.status != Status.NoDispute) revert TransactionDisputed();\\n\\n uint256 amount = transaction.amount;\\n transaction.amount = 0;\\n transaction.status = Status.TransactionResolved;\\n\\n if (transaction.token == NATIVE) {\\n transaction.seller.send(amount); // It is the user responsibility to accept ETH.\\n } else {\\n if (!transaction.token.safeTransfer(transaction.seller, amount)) revert TokenTransferFailed();\\n }\\n\\n emit Payment(_transactionID, amount, transaction.buyer);\\n emit TransactionResolved(_transactionID, Resolution.TransactionExecuted);\\n }\\n\\n /// @inheritdoc IEscrow\\n function proposeSettlement(uint256 _transactionID, uint256 _amount) external override {\\n Transaction storage transaction = transactions[_transactionID];\\n if (transaction.status == Status.NoDispute && block.timestamp >= transaction.deadline)\\n revert TransactionExpired();\\n if (transaction.status >= Status.WaitingBuyer) revert TransactionEscalatedForArbitration();\\n if (_amount > transaction.amount) revert MaximumPaymentAmountExceeded();\\n\\n Party party;\\n transaction.lastFeePaymentTime = block.timestamp;\\n if (transaction.status == Status.WaitingSettlementBuyer) {\\n if (msg.sender != transaction.buyer) revert BuyerOnly();\\n transaction.settlementBuyer = _amount;\\n transaction.status = Status.WaitingSettlementSeller;\\n party = Party.Buyer;\\n } else if (transaction.status == Status.WaitingSettlementSeller) {\\n if (msg.sender != transaction.seller) revert SellerOnly();\\n transaction.settlementSeller = _amount;\\n transaction.status = Status.WaitingSettlementBuyer;\\n party = Party.Seller;\\n } else {\\n if (msg.sender == transaction.buyer) {\\n transaction.settlementBuyer = _amount;\\n transaction.status = Status.WaitingSettlementSeller;\\n party = Party.Buyer;\\n } else if (msg.sender == transaction.seller) {\\n transaction.settlementSeller = _amount;\\n transaction.status = Status.WaitingSettlementBuyer;\\n party = Party.Seller;\\n } else revert BuyerOrSellerOnly();\\n }\\n emit SettlementProposed(_transactionID, party, _amount);\\n }\\n\\n /// @inheritdoc IEscrow\\n function acceptSettlement(uint256 _transactionID) external override {\\n Transaction storage transaction = transactions[_transactionID];\\n uint256 settlementAmount;\\n if (transaction.status == Status.WaitingSettlementBuyer) {\\n if (msg.sender != transaction.buyer) revert BuyerOnly();\\n settlementAmount = transaction.settlementSeller;\\n } else if (transaction.status == Status.WaitingSettlementSeller) {\\n if (msg.sender != transaction.seller) revert SellerOnly();\\n settlementAmount = transaction.settlementBuyer;\\n } else revert NoSettlementProposedOrTransactionMovedOnAcceptSettlement();\\n\\n uint256 remainingAmount = transaction.amount - settlementAmount;\\n\\n transaction.amount = 0;\\n transaction.settlementBuyer = 0;\\n transaction.settlementSeller = 0;\\n transaction.status = Status.TransactionResolved;\\n\\n if (transaction.token == NATIVE) {\\n // It is the users' responsibility to accept ETH.\\n transaction.buyer.send(remainingAmount);\\n transaction.seller.send(settlementAmount);\\n } else {\\n transaction.token.safeTransfer(transaction.buyer, remainingAmount);\\n transaction.token.safeTransfer(transaction.seller, settlementAmount);\\n }\\n\\n emit TransactionResolved(_transactionID, Resolution.SettlementReached);\\n }\\n\\n /// @inheritdoc IEscrow\\n function payArbitrationFeeByBuyer(uint256 _transactionID) external payable override {\\n Transaction storage transaction = transactions[_transactionID];\\n if (\\n transaction.status != Status.WaitingSettlementBuyer &&\\n transaction.status != Status.WaitingSettlementSeller &&\\n transaction.status != Status.WaitingBuyer\\n ) revert NoSettlementProposedOrTransactionMovedOnPayFeeBuyer();\\n\\n // Allow the other party enough time to respond to a settlement before allowing the proposer to raise a dispute.\\n if (\\n transaction.status == Status.WaitingSettlementSeller &&\\n block.timestamp - transaction.lastFeePaymentTime < settlementTimeout\\n ) revert SettlementPeriodNotOver();\\n\\n if (msg.sender != transaction.buyer) revert BuyerOnly();\\n\\n transaction.buyerFee += msg.value;\\n uint256 arbitrationCost = arbitrator.arbitrationCost(arbitratorExtraData);\\n if (transaction.buyerFee < arbitrationCost) revert BuyerFeeNotCoverArbitrationCosts();\\n\\n transaction.lastFeePaymentTime = block.timestamp;\\n\\n if (transaction.sellerFee < arbitrationCost) {\\n // The seller still has to pay. This can also happen if he has paid, but arbitrationCost has increased.\\n transaction.status = Status.WaitingSeller;\\n emit HasToPayFee(_transactionID, Party.Seller);\\n } else {\\n // The seller has also paid the fee. We create the dispute.\\n raiseDispute(_transactionID, arbitrationCost);\\n }\\n }\\n\\n /// @inheritdoc IEscrow\\n function payArbitrationFeeBySeller(uint256 _transactionID) external payable override {\\n Transaction storage transaction = transactions[_transactionID];\\n if (\\n transaction.status != Status.WaitingSettlementBuyer &&\\n transaction.status != Status.WaitingSettlementSeller &&\\n transaction.status != Status.WaitingSeller\\n ) revert NoSettlementProposedOrTransactionMovedOnPayFeeSeller();\\n\\n // Allow the other party enough time to respond to a settlement before allowing the proposer to raise a dispute.\\n if (\\n transaction.status == Status.WaitingSettlementBuyer &&\\n block.timestamp - transaction.lastFeePaymentTime < settlementTimeout\\n ) revert SettlementPeriodNotOver();\\n\\n if (msg.sender != transaction.seller) revert SellerOnly();\\n\\n transaction.sellerFee += msg.value;\\n uint256 arbitrationCost = arbitrator.arbitrationCost(arbitratorExtraData);\\n if (transaction.sellerFee < arbitrationCost) revert SellerFeeNotCoverArbitrationCosts();\\n\\n transaction.lastFeePaymentTime = block.timestamp;\\n\\n if (transaction.buyerFee < arbitrationCost) {\\n // The buyer still has to pay. This can also happen if he has paid, but arbitrationCost has increased.\\n transaction.status = Status.WaitingBuyer;\\n emit HasToPayFee(_transactionID, Party.Buyer);\\n } else {\\n // The buyer has also paid the fee. We create the dispute.\\n raiseDispute(_transactionID, arbitrationCost);\\n }\\n }\\n\\n /// @inheritdoc IEscrow\\n function timeOutByBuyer(uint256 _transactionID) external override {\\n Transaction storage transaction = transactions[_transactionID];\\n if (transaction.status != Status.WaitingSeller) revert NotWaitingForSellerFees();\\n if (block.timestamp - transaction.lastFeePaymentTime < feeTimeout) revert TimeoutNotPassed();\\n\\n uint256 amount = transaction.sellerFee;\\n transaction.sellerFee = 0;\\n\\n executeRuling(_transactionID, uint256(Party.Buyer));\\n\\n if (amount != 0) {\\n transaction.seller.send(amount); // It is the user responsibility to accept ETH.\\n }\\n\\n emit TransactionResolved(_transactionID, Resolution.TimeoutByBuyer);\\n }\\n\\n /// @inheritdoc IEscrow\\n function timeOutBySeller(uint256 _transactionID) external override {\\n Transaction storage transaction = transactions[_transactionID];\\n if (transaction.status != Status.WaitingBuyer) revert NotWaitingForBuyerFees();\\n if (block.timestamp - transaction.lastFeePaymentTime < feeTimeout) revert TimeoutNotPassed();\\n\\n uint256 amount = transaction.buyerFee;\\n transaction.buyerFee = 0;\\n\\n executeRuling(_transactionID, uint256(Party.Seller));\\n\\n if (amount != 0) {\\n transaction.buyer.send(amount); // It is the user responsibility to accept ETH.\\n }\\n\\n emit TransactionResolved(_transactionID, Resolution.TimeoutBySeller);\\n }\\n\\n /// @inheritdoc IArbitrableV2\\n function rule(uint256 _disputeID, uint256 _ruling) external override {\\n if (msg.sender != address(arbitrator)) revert ArbitratorOnly();\\n if (_ruling > AMOUNT_OF_CHOICES) revert InvalidRuling();\\n\\n uint256 transactionID = disputeIDtoTransactionID[_disputeID];\\n Transaction storage transaction = transactions[transactionID];\\n if (transaction.status != Status.DisputeCreated) revert DisputeAlreadyResolved();\\n\\n emit Ruling(arbitrator, _disputeID, _ruling);\\n emit TransactionResolved(transactionID, Resolution.RulingEnforced);\\n executeRuling(transactionID, _ruling);\\n }\\n\\n // ************************************* //\\n // * Internal * //\\n // ************************************* //\\n\\n /// @dev Create a dispute.\\n /// @param _transactionID The index of the transaction.\\n /// @param _arbitrationCost Amount to pay the arbitrator.\\n function raiseDispute(uint256 _transactionID, uint256 _arbitrationCost) internal {\\n Transaction storage transaction = transactions[_transactionID];\\n transaction.status = Status.DisputeCreated;\\n transaction.disputeID = arbitrator.createDispute{value: _arbitrationCost}(\\n AMOUNT_OF_CHOICES,\\n arbitratorExtraData\\n );\\n disputeIDtoTransactionID[transaction.disputeID] = _transactionID;\\n emit DisputeRequest(arbitrator, transaction.disputeID, _transactionID, templateId, \\\"\\\");\\n\\n // Refund buyer if he overpaid.\\n if (transaction.buyerFee > _arbitrationCost) {\\n uint256 extraFeeBuyer = transaction.buyerFee - _arbitrationCost;\\n transaction.buyerFee = _arbitrationCost;\\n transaction.buyer.send(extraFeeBuyer); // It is the user responsibility to accept ETH.\\n }\\n\\n // Refund seller if he overpaid.\\n if (transaction.sellerFee > _arbitrationCost) {\\n uint256 extraFeeSeller = transaction.sellerFee - _arbitrationCost;\\n transaction.sellerFee = _arbitrationCost;\\n transaction.seller.send(extraFeeSeller); // It is the user responsibility to accept ETH.\\n }\\n }\\n\\n /// @dev Execute a ruling of a dispute. It reimburses the fee to the winning party.\\n /// @param _transactionID The index of the transaction.\\n /// @param _ruling Ruling given by the arbitrator. 1 : Reimburse the seller. 2 : Pay the buyer.\\n function executeRuling(uint256 _transactionID, uint256 _ruling) internal {\\n Transaction storage transaction = transactions[_transactionID];\\n address payable buyer = transaction.buyer;\\n address payable seller = transaction.seller;\\n\\n (uint256 buyerPayout, uint256 buyerPayoutToken, uint256 sellerPayout, uint256 sellerPayoutToken) = getPayouts(\\n _transactionID,\\n Party(_ruling)\\n );\\n\\n transaction.amount = 0;\\n transaction.settlementBuyer = 0;\\n transaction.settlementSeller = 0;\\n transaction.buyerFee = 0;\\n transaction.sellerFee = 0;\\n transaction.status = Status.TransactionResolved;\\n\\n if (buyerPayout > 0) {\\n buyer.send(buyerPayout); // It is the user responsibility to accept ETH.\\n }\\n if (sellerPayout > 0) {\\n seller.send(sellerPayout); // It is the user responsibility to accept ETH.\\n }\\n if (buyerPayoutToken > 0) {\\n transaction.token.safeTransfer(buyer, buyerPayoutToken); // Tokens should not reenter or allow recipients to refuse the transfer.\\n }\\n if (sellerPayoutToken > 0) {\\n transaction.token.safeTransfer(seller, sellerPayoutToken); // Tokens should not reenter or allow recipients to refuse the transfer.\\n }\\n }\\n\\n // ************************************* //\\n // * Public Views * //\\n // ************************************* //\\n\\n /// @inheritdoc IEscrow\\n function getTransactionCount() external view override returns (uint256) {\\n return transactions.length;\\n }\\n\\n /// @dev Get the payout depending on the winning party.\\n /// @dev The cost for the buyer is the seller payout non-inclusive of any arbitration fees.\\n /// @param _transactionID The index of the transaction.\\n /// @param _winningParty The winning party.\\n /// @return buyerPayout The payout for the buyer.\\n /// @return buyerPayoutToken The payout for the buyer in tokens.\\n /// @return sellerPayout The payout for the seller.\\n /// @return sellerPayoutToken The payout for the seller in tokens.\\n function getPayouts(\\n uint256 _transactionID,\\n Party _winningParty\\n )\\n public\\n view\\n returns (uint256 buyerPayout, uint256 buyerPayoutToken, uint256 sellerPayout, uint256 sellerPayoutToken)\\n {\\n Transaction storage transaction = transactions[_transactionID];\\n uint256 amount = transaction.amount;\\n uint256 settlementBuyer = transaction.settlementBuyer;\\n uint256 settlementSeller = transaction.settlementSeller;\\n uint256 buyerFee = transaction.buyerFee;\\n uint256 sellerFee = transaction.sellerFee;\\n bool nativePayment = transaction.token == NATIVE;\\n if (_winningParty == Party.Buyer) {\\n // The Seller gets the settlement amount proposed by the Buyer if any, otherwise nothing.\\n // The Buyer gets the remaining amount of the transaction back if any.\\n // The Buyer gets the arbitration fee back.\\n uint256 settledAmount = settlementBuyer;\\n if (nativePayment) {\\n buyerPayout = buyerFee + amount - settledAmount;\\n sellerPayout = settledAmount;\\n } else {\\n buyerPayout = buyerFee;\\n buyerPayoutToken = amount - settledAmount;\\n sellerPayoutToken = settledAmount;\\n }\\n } else if (_winningParty == Party.Seller) {\\n // The Seller gets his proposed settlement amount if any, otherwise the transaction amount.\\n // The Buyer gets the remaining amount of the transaction back if any.\\n // The Seller gets the arbitration fee back.\\n uint256 settledAmount = settlementSeller != 0 ? settlementSeller : amount;\\n if (nativePayment) {\\n buyerPayout = amount - settledAmount;\\n sellerPayout = sellerFee + settledAmount;\\n } else {\\n buyerPayoutToken = amount - settledAmount;\\n sellerPayout = sellerFee;\\n sellerPayoutToken = settledAmount;\\n }\\n } else {\\n // No party wins, we split the arbitration fee and the transaction amount.\\n // The arbitration fee has been paid twice, once by the Buyer and once by the Seller in equal amount once arbitration starts.\\n // In case of an uneven token amount, one basic token unit can be burnt.\\n uint256 splitArbitrationFee = buyerFee / 2; // buyerFee equals sellerFee.\\n buyerPayout = splitArbitrationFee;\\n sellerPayout = splitArbitrationFee;\\n uint256 splitAmount = amount / 2;\\n if (nativePayment) {\\n buyerPayout += splitAmount;\\n sellerPayout += splitAmount;\\n } else {\\n buyerPayoutToken = splitAmount;\\n sellerPayoutToken = splitAmount;\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xbcd7fe39d1afba3d14cedaffe8449f284e48595808aa33e1fd08be0b933f97fc\",\"license\":\"MIT\"},\"src/interfaces/IEscrow.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.8.24;\\n\\nimport \\\"./Types.sol\\\";\\n\\ninterface IEscrow {\\n // ************************************* //\\n // * Events * //\\n // ************************************* //\\n\\n /// @dev To be emitted when Escrow parameters are updated.\\n event ParameterUpdated(uint256 _feeTimeout, uint256 _settlementTimeout, bytes _arbitratorExtraData);\\n\\n /// @dev To be emitted when a party pays or reimburses the other.\\n /// @param _transactionID The index of the transaction.\\n /// @param _amount The amount paid.\\n /// @param _party The party that paid.\\n event Payment(uint256 indexed _transactionID, uint256 _amount, address _party);\\n\\n /// @dev Indicate that a party has to pay a fee or would otherwise be considered as losing.\\n /// @param _transactionID The index of the transaction.\\n /// @param _party The party who has to pay.\\n event HasToPayFee(uint256 indexed _transactionID, Party _party);\\n\\n /// @dev Emitted when a party proposes a settlement.\\n /// @param _transactionID The index of the transaction.\\n /// @param _party The party that proposed a settlement.\\n /// @param _amount The amount proposed.\\n event SettlementProposed(uint256 indexed _transactionID, Party _party, uint256 _amount);\\n\\n /// @dev Emitted when a transaction paid in native currency is created.\\n /// @param _transactionID The index of the transaction.\\n /// @param _transactionUri The IPFS Uri Hash of the transaction.\\n /// @param _buyer The address of the buyer.\\n /// @param _seller The address of the seller.\\n /// @param _amount The initial amount in the transaction.\\n /// @param _deadline The deadline of the transaction.\\n event NativeTransactionCreated(\\n uint256 indexed _transactionID,\\n string _transactionUri,\\n address indexed _buyer,\\n address indexed _seller,\\n uint256 _amount,\\n uint256 _deadline\\n );\\n\\n /// @dev Emitted when a transaction paid in ERC20 token is created.\\n /// @param _transactionID The index of the transaction.\\n /// @param _transactionUri The IPFS Uri Hash of the transaction.\\n /// @param _buyer The address of the buyer.\\n /// @param _seller The address of the seller.\\n /// @param _token The token address.\\n /// @param _amount The initial amount in the transaction.\\n /// @param _deadline The deadline of the transaction.\\n event ERC20TransactionCreated(\\n uint256 indexed _transactionID,\\n string _transactionUri,\\n address indexed _buyer,\\n address indexed _seller,\\n IERC20 _token,\\n uint256 _amount,\\n uint256 _deadline\\n );\\n\\n /// @dev To be emitted when a transaction is resolved, either by its\\n /// execution, a timeout or because a ruling was enforced.\\n /// @param _transactionID The ID of the respective transaction.\\n /// @param _resolution Short description of what caused the transaction to be solved.\\n event TransactionResolved(uint256 indexed _transactionID, Resolution indexed _resolution);\\n\\n // ************************************* //\\n // * State Modifiers * //\\n // ************************************* //\\n\\n /// @dev Create a transaction.\\n /// @param _deadline Time after which a party can automatically execute the arbitrable transaction.\\n /// @param _transactionUri The IPFS Uri Hash of the transaction.\\n /// @param _seller The recipient of the transaction.\\n /// @return transactionID The index of the transaction.\\n function createNativeTransaction(\\n uint256 _deadline,\\n string memory _transactionUri,\\n address payable _seller\\n ) external payable returns (uint256 transactionID);\\n\\n /// @dev Create a transaction.\\n /// @param _amount The amount of tokens in this transaction.\\n /// @param _token The ERC20 token contract.\\n /// @param _deadline Time after which a party can automatically execute the arbitrable transaction.\\n /// @param _transactionUri The IPFS Uri Hash of the transaction.\\n /// @param _seller The recipient of the transaction.\\n /// @return transactionID The index of the transaction.\\n function createERC20Transaction(\\n uint256 _amount,\\n IERC20 _token,\\n uint256 _deadline,\\n string memory _transactionUri,\\n address payable _seller\\n ) external returns (uint256 transactionID);\\n\\n /// @dev Pay seller. To be called if the good or service is provided.\\n /// @param _transactionID The index of the transaction.\\n /// @param _amount Amount to pay in wei.\\n function pay(uint256 _transactionID, uint256 _amount) external;\\n\\n /// @dev Reimburse buyer. To be called if the good or service can't be fully provided.\\n /// @param _transactionID The index of the transaction.\\n /// @param _amountReimbursed Amount to reimburse in wei.\\n function reimburse(uint256 _transactionID, uint256 _amountReimbursed) external;\\n\\n /// @dev Transfer the transaction's amount to the seller if the timeout has passed.\\n /// @param _transactionID The index of the transaction.\\n function executeTransaction(uint256 _transactionID) external;\\n\\n /// @dev Propose a settlement as a compromise from the initial terms to the other party.\\n /// Note that a party can only propose a settlement again after the other party has\\n /// done so as well to prevent front running/griefing issues.\\n /// @param _transactionID The index of the transaction.\\n /// @param _amount The settlement amount.\\n function proposeSettlement(uint256 _transactionID, uint256 _amount) external;\\n\\n /// @dev Accept a settlement proposed by the other party.\\n /// @param _transactionID The index of the transaction.\\n function acceptSettlement(uint256 _transactionID) external;\\n\\n /// @dev Pay the arbitration fee to raise a dispute. To be called by the buyer.\\n /// Note that it can only be called after settlement proposition.\\n /// Also note that the arbitrator can have createDispute throw, which will make\\n /// this function throw and therefore lead to a party being timed-out.\\n /// This is not a vulnerability as the arbitrator can rule in favor of one party anyway.\\n /// @param _transactionID The index of the transaction.\\n function payArbitrationFeeByBuyer(uint256 _transactionID) external payable;\\n\\n /// @dev Pay the arbitration fee to raise a dispute. To be called by the seller.\\n /// Note that this function mirrors payArbitrationFeeByBuyer.\\n /// @param _transactionID The index of the transaction.\\n function payArbitrationFeeBySeller(uint256 _transactionID) external payable;\\n\\n /// @dev Reimburse buyer if seller fails to pay the fee.\\n /// @param _transactionID The index of the transaction.\\n function timeOutByBuyer(uint256 _transactionID) external;\\n\\n /// @dev Pay seller if buyer fails to pay the fee.\\n /// @param _transactionID The index of the transaction.\\n function timeOutBySeller(uint256 _transactionID) external;\\n\\n // ************************************* //\\n // * Public Views * //\\n // ************************************* //\\n\\n /// @dev Getter to know the count of transactions.\\n /// @return The count of transactions.\\n function getTransactionCount() external view returns (uint256);\\n\\n // ************************************* //\\n // * Errors * //\\n // ************************************* //\\n\\n error GovernorOnly();\\n error BuyerOnly();\\n error SellerOnly();\\n error BuyerOrSellerOnly();\\n error ArbitratorOnly();\\n error TransactionDisputed();\\n error MaximumPaymentAmountExceeded();\\n error DeadlineNotPassed();\\n error BuyerFeeNotCoverArbitrationCosts();\\n error SellerFeeNotCoverArbitrationCosts();\\n error NotWaitingForSellerFees();\\n error NotWaitingForBuyerFees();\\n error TimeoutNotPassed();\\n error InvalidRuling();\\n error DisputeAlreadyResolved();\\n error TransactionExpired();\\n error TransactionEscalatedForArbitration();\\n error NoSettlementProposedOrTransactionMovedOnAcceptSettlement();\\n error NoSettlementProposedOrTransactionMovedOnPayFeeBuyer();\\n error NoSettlementProposedOrTransactionMovedOnPayFeeSeller();\\n error SettlementPeriodNotOver();\\n error NotSupported();\\n error TokenTransferFailed();\\n error AmountExceedsCap();\\n}\\n\",\"keccak256\":\"0x4dc29ec253ae0e2598846b4721ac03ec85c75c1f7ad8a1920290abbf411eafe2\",\"license\":\"MIT\"},\"src/interfaces/Types.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.24;\\n\\nimport {IERC20} from \\\"../libraries/SafeERC20.sol\\\";\\n\\nIERC20 constant NATIVE = IERC20(address(0));\\n\\nenum Party {\\n None,\\n Buyer, // Makes a purchase in native currency or ERC20 token.\\n Seller // Provides a good or service in exchange for native currency or ERC20 token.\\n}\\n\\nenum Status {\\n NoDispute,\\n WaitingSettlementBuyer,\\n WaitingSettlementSeller,\\n WaitingBuyer,\\n WaitingSeller,\\n DisputeCreated,\\n TransactionResolved\\n}\\n\\nenum Resolution {\\n TransactionExecuted,\\n TimeoutByBuyer,\\n TimeoutBySeller,\\n RulingEnforced,\\n SettlementReached\\n}\\n\\nstruct Transaction {\\n address payable buyer;\\n address payable seller;\\n uint256 amount;\\n uint256 settlementBuyer; // Settlement amount proposed by the buyer.\\n uint256 settlementSeller; // Settlement amount proposed by the seller.\\n uint256 deadline; // Timestamp at which the transaction can be automatically executed if not disputed.\\n uint256 disputeID; // If dispute exists, the ID of the dispute.\\n uint256 buyerFee; // Total fees paid by the buyer.\\n uint256 sellerFee; // Total fees paid by the seller.\\n uint256 lastFeePaymentTime; // Last time the dispute fees were paid by either party or settlement proposed.\\n Status status;\\n IERC20 token; // Token to pay the seller with.\\n}\\n\",\"keccak256\":\"0xa35119fdfdeb0f514e8c996d115303f916a95eff6003fdb9c1a8540f64d21ddb\",\"license\":\"MIT\"},\"src/libraries/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// Adapted from https://github.com/OpenZeppelin/openzeppelin-contracts/blob/a7a94c77463acea95d979aae1580fb0ddc3b6a1e/contracts/token/ERC20/utils/SafeERC20.sol\\n\\npragma solidity 0.8.24;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\n/// @title SafeERC20\\n/// @dev Wrappers around ERC20 operations that throw on failure (when the token\\n/// contract returns false). Tokens that return no value (and instead revert or\\n/// throw on failure) are also supported, non-reverting calls are assumed to be\\n/// successful.\\n/// To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n/// which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\nlibrary SafeERC20 {\\n /// @dev Calls transfer() without reverting.\\n /// @param _token Token to transfer.\\n /// @param _to Recepient address.\\n /// @param _value Amount transferred.\\n /// @return Whether transfer succeeded or not.\\n function safeTransfer(IERC20 _token, address _to, uint256 _value) internal returns (bool) {\\n (bool success, bytes memory data) = address(_token).call(abi.encodeCall(IERC20.transfer, (_to, _value)));\\n return (success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n /// @dev Calls transferFrom() without reverting.\\n /// @param _token Token to transfer.\\n /// @param _from Sender address.\\n /// @param _to Recepient address.\\n /// @param _value Amount transferred.\\n /// @return Whether transfer succeeded or not.\\n function safeTransferFrom(IERC20 _token, address _from, address _to, uint256 _value) internal returns (bool) {\\n (bool success, bytes memory data) = address(_token).call(\\n abi.encodeCall(IERC20.transferFrom, (_from, _to, _value))\\n );\\n return (success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\",\"keccak256\":\"0x3a53cfe0db97fcacb3a92c085bd9d7dfe86cc3005021dfd7c372374ab13f8e84\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60808060405234620002665762002c6a8038038091620000208285620003ad565b833981019060e081830312620002665780516001600160a01b03928382169291839003620002665760208201516001600160401b03908181116200026657830182601f820112156200026657828160206200007e93519101620003f6565b9460408401518281116200026657836200009a91860162000442565b926060850151908382116200026657620000b691860162000442565b926080850151928284168403620002665760c060a0870151960151963360018060a01b0319600054161760005560018060a01b0319600154161760015587519081116200039757600254600181811c911680156200038c575b60208210146200037657601f81116200030c575b506020601f82116001146200028c57620001c695936020959383620001b394600094859162000280575b508160011b9185199060031b1c1916176002555b600380546001600160a01b031916868416179055600589905560068a90556040516312a6505d60e21b815260606004820152606481018490526080602482015297889687958693608485019062000462565b8381036003190160448501529062000462565b0393165af1908115620002745760009162000228575b5060008051602062002c4a8339815191529362000215916004556040519384938452602084015260606040840152606083019062000462565b0390a16040516127c090816200048a8239f35b90506020813d6020116200026b575b816200024660209383620003ad565b8101031262000266575160008051602062002c4a833981519152620001dc565b600080fd5b3d915062000237565b6040513d6000823e3d90fd5b90508c0151386200014d565b601f1982169060026000528960206000209260005b818110620002f1575084600094620001c69a989460209a9894620001b39860019510620002d8575b505050811b0160025562000161565b0151861960f88460031b161c1916905538808e620002c9565b9183015184556001909301926020928301928c9201620002a1565b60026000527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace601f830160051c810191602084106200036b575b601f0160051c01905b8181106200035e575062000123565b600081556001016200034f565b909150819062000346565b634e487b7160e01b600052602260045260246000fd5b90607f16906200010f565b634e487b7160e01b600052604160045260246000fd5b601f909101601f19168101906001600160401b038211908210176200039757604052565b60005b838110620003e55750506000910152565b8181015183820152602001620003d4565b919291906001600160401b03811162000397576040519162000423601f8301601f191660200184620003ad565b8294828452828201116200026657602062000440930190620003d1565b565b9080601f83011215620002665781516200045f92602001620003f6565b90565b906020916200047d81518092818552858086019101620003d1565b601f01601f191601019056fe6040608081526004908136101561001557600080fd5b600090813560e01c8063040c488814611f045780630c340a2414611edd5780630c7ac7b614611e0d5780631bd1823a14611bf65780632a7027de14611aee5780632be6d005146119115780632e0b6422146118f65780632e7700f0146118d85780632fbe3b03146118b0578063311a6c56146116d257806334e2672d146115005780633bf547241461130f578063441080fe146112f15780634660ebbe146112a65780634ab162e2146111465780636cc6cde11461111e5780637aa77f2914611100578063871fbf86146110b857806393ee267814610f305780639ace38c214610e54578063a0af81f014610e2c578063b2b9679214610c44578063b329036b14610c26578063c5d5528814610b11578063cb44c3fa14610ab3578063d2b8ae9c14610a64578063e3f07e9014610904578063e4c0aaf4146108ba578063e77d0bd31461068e578063e98c579b1461061b578063ee22610b146104c7578063ef48eee6146103ac578063f05a59f914610375578063fc548f08146103155763fe43a992146101a257600080fd5b34610311576101b036612162565b9190936101bc856121a4565b5060018101546001600160a01b039391929190841633810361030357600a84019081549060ff821660078110156102f0576102e0576002860190815490818a116102d05785518a81526001600160a01b039091166020820152999a8b9a8995948c949293909291610249918d91869060008051602061276b8339815191529080604081015b0390a26121fc565b809155156102ad575b5050505460081c16801560001461028457505050839283928392541682821561027b575bf15080f35b506108fc610276565b919550939192610296935416906126cd565b156102a057505080f35b5163022e258160e11b8152fd5b60ff1916600617835560008051602061272b8339815191528280a3873880610252565b85516305aafecf60e01b81528790fd5b50505051634e22597f60e11b8152fd5b634e487b7160e01b8a526021865260248afd5b5051635800797f60e11b8152fd5b5080fd5b5082346103715760203660031901126103715780356001600160a01b03818116939184900361036d578454163303610360575050600180546001600160a01b03191691909117905580f35b5163c383977560e01b8152fd5b8480fd5b8280fd5b50346103115760203660031901126103115760209181906001600160a01b0361039c61218e565b1681526009845220549051908152f35b5034610311576103bb36612162565b9190936103c7856121a4565b5080546001600160a01b03939192919084163381036104b957600a84019081549060ff821660078110156102f0576102e0576002860190815490818a116102d05785518a81526001600160a01b039091166020820152999a8b9a8995948c94929390929161044d918d91869060008051602061276b833981519152908060408101610241565b80915515610496575b5050505460081c16801560001461048157505050839283926001849301541682821561027b57f15080f35b919550939192600161029694015416906126cd565b60ff1916600617835560008051602061272b8339815191528280a3873880610456565b505163e2bc376b60e01b8152fd5b509134610311576020366003190112610311578035906104e6826121a4565b506005810154421061060c57600a81019081549260ff841660078110156105f9576105eb576002820180549087905560ff19909416600617928390556001600160a01b039260081c8316806105a857505094826105878388888080808b9a60008051602061276b8339815191529a829f600101541682821561059f575bf1505b5493519283529092166001600160a01b031660208201529081906040820190565b0390a260008051602061272b8339815191528280a380f35b506108fc610563565b846105ba9185600186015416906126cd565b156105dd575094839261058760008051602061276b833981519152938798610566565b865163022e258160e11b8152fd5b8651634e22597f60e11b8152fd5b634e487b7160e01b875260218252602487fd5b5083516302eb354360e41b8152fd5b50829034610371576020366003190112610371578254823592906001600160a01b03163303610680575090606060008051602061274b833981519152928260065560055492815193845260208401528201528061067a6060820161224e565b0390a180f35b905163c383977560e01b8152fd5b5034610311576020366003190112610311578235906106ac826121a4565b509060ff600a8301541660078110156108a7578503610898576106d36009830154426121fc565b600554116108895750918281946008600195019183835493556106f5856121a4565b5091868060a01b039283815416848983015416908788809581956107188d6121a4565b506002810154906003810154998c600a600784015493015460081c161560001461086b575091846107558b610750600a958497612241565b6121fc565b9a945b8160028401558160038401558201558260078201558260088201550197600660ff198a5416178955858115801561084a575b505050508481158015610829575b5050505080610811575b505084826107f9575b5050505082159283156107d2575b505050508060008051602061272b83398151915291a380f35b849384938885940154169083906107f0575bf15082388080806107b9565b506108fc6107e4565b610807935460081c166126cd565b50388080846107ab565b6108219187865460081c166126cd565b5038806107a2565b8392839283928390610841575bf15088388481610798565b506108fc610836565b8392839283928390610862575bf1508138858161078a565b506108fc610857565b9398508995509184610882600a939b82959c6121fc565b9699610758565b51634799187b60e01b81528490fd5b51638225aba560e01b81528490fd5b634e487b7160e01b855260218652602485fd5b50829034610371576020366003190112610371576001600160a01b0382358181169391929084900361036d5784549233908416036103605750506001600160a01b03191617815580f35b50346103115760a0366003190112610311578235610920612178565b604435916064356001600160401b038111610a60576109429036908801612070565b9161094b6120d2565b6001600160a01b038281168852600960205286882054909591908411610a50576109778430338661263d565b15610a4057600582916109886121d9565b5080546001600160a01b0319908116331782556001820180549091169990921698891790915560028101869055600a81018054610100600160a81b031916600887901b610100600160a81b03161790550155600754600019810197908811610a2d575060209750917fb96ca2c0c34e2ad6384277748b8101f4bddc3cbeaad7086e59cd315bd19aa8c591610a24889488519384933398856122e0565b0390a451908152f35b634e487b7160e01b815260118952602490fd5b865163022e258160e11b81528990fd5b8651631d9c3dff60e31b81528990fd5b8580fd5b508234610371578160031936011261037157610a7e61218e565b83546001600160a01b03929083163303610aa5575016825260096020526024359082205580f35b835163c383977560e01b8152fd5b50829034610371576020366003190112610371578254823592906001600160a01b03163303610680575090606060008051602061274b8339815191529282600555600654815193845260208401528201528061067a6060820161224e565b508234610371576003198281360112610c22576001600160401b038235818111610a6057610b429036908501612070565b90602435908111610a6057610b5a9036908501612070565b85549091906001600160a01b039081163303610c125790610bb187602094936003541692610bc08951978896879586946312a6505d60e21b865260608d870152866064870152608060248701526084860190612122565b91848303016044850152612122565b03925af1928315610c0957508392610bd757505580f35b9091506020813d602011610c01575b81610bf36020938361201e565b810103126103715751905580f35b3d9150610be6565b513d85823e3d90fd5b855163c383977560e01b81528590fd5b8380fd5b50346103115781600319360112610311576020906005549051908152f35b503461031157610c5336612162565b610c5e8293926121a4565b50600a8101805460ff8116926007841015610e1957831580610e0b575b610dfb576003841015610deb5788600292838301548711610ddc578690426009850155600196878114600014610d3257505082546001600160a01b031633039150610d22905057600301849055815460ff1916179055905b8251916003811015610d0f577f10c8b22b69e324b0227c6adfa65183c771304c11385423e93ce99779a7483dbf9495965082526020820152a280f35b634e487b7160e01b865260218752602486fd5b855163e2bc376b60e01b81528990fd5b9496949293928703610d75575050808301546001600160a01b03163303610d665701849055815460ff191617905590610cd3565b508551635800797f60e11b8152fd5b8254949694919390916001600160a01b03903390821603610da65750505060030155815460ff191617905590610cd3565b909291935086829795970154163314600014610dcd570185905560ff191617905590610cd3565b50865163351c18ff60e21b8152fd5b5086516305aafecf60e01b8152fd5b8551630d71592960e31b81528990fd5b85516338e5e54b60e21b81528990fd5b506005810154421015610c7b565b634e487b7160e01b885260218952602488fd5b503461031157816003193601126103115760035490516001600160a01b039091168152602090f35b503461031157602036600319011261031157823560075481101561037157610e7b906121a4565b5090600160a01b60019003918281541693836001830154169160028101546003820154888301546005840154600685015491600786015493600887015495600988015497600a01549a60ff8c169a81519e8f908152602001528d015260608c015260808b015260a08a015260c089015260e08801526101008701526101208601526007821015610f1d5750610180945061014084015260081c16610160820152f35b634e487b7160e01b815260218652602490fd5b5082903461037157602036600319011261037157813590610f50826121a4565b50600a81019182549060ff821660078110156110a5576001810361105d575082546001600160a01b0316330361104e575090859185820154915b6006600282019285610f9d8686546121fc565b94556003830186905588830186905560ff19161780865560081c6001600160a01b03908116959092908661101f575084955091600182868080808099979887829a5416828215611016575bf15001541682821561100d575bf1505b60008051602061272b8339815191528380a380f35b506108fc610ff5565b506108fc610fe8565b82949550611038849261104898846001965416906126cd565b505460081c1692015416906126cd565b50610ff8565b5163e2bc376b60e01b81528590fd5b6002036110965760018301546001600160a01b031633036110875750908591600382015491610f8a565b51635800797f60e11b81528590fd5b51630a7b6ec160e01b81528590fd5b634e487b7160e01b885260218752602488fd5b5082346103715781600319360112610371576024359260038410156110fd57506080926110e59135612312565b92939091815194855260208501528301526060820152f35b80fd5b50823461037157826003193601126103715760209250549051908152f35b503461031157816003193601126103115760015490516001600160a01b039091168152602090f35b50346103115760c0366003190112610311578235611162612178565b604435906064356001600160401b038111610a60576111849036908801612070565b61118c6120d2565b9260a4359460018060a01b038087168097036112a25780851689526009602052878920548211611292576111c28230338861263d565b1561128257600583916111d36121d9565b5080546001600160a01b03199081169290991691821781556001810180549099168a1790985560028801849055600a88018054610100600160a81b031916600889901b610100600160a81b031617905596015560075460001981019890891161126f57506020985091610a248894927fb96ca2c0c34e2ad6384277748b8101f4bddc3cbeaad7086e59cd315bd19aa8c5948951948594856122e0565b634e487b7160e01b815260118a52602490fd5b875163022e258160e11b81528a90fd5b8751631d9c3dff60e31b81528a90fd5b8880fd5b5082346103715760203660031901126103715780356001600160a01b03818116939184900361036d578454163303610360575050600380546001600160a01b03191691909117905580f35b50346103115781600319360112610311576020906006549051908152f35b508290602080600319360112610c225782359161132b836121a4565b50600a81019060ff8254166007811015806114ed576001821491821590816114de575b82826114ba575b50506114aa576110a55780611492575b6114825760018101546001600160a01b03969087163303611474576008820196611390348954612241565b8098556001541696858551809963f7434ea960e01b8252828583015281806113ba6024820161224e565b03915afa97881561146a57899861143b575b50871161142d57504260098201556007015485111561141d577fc74b9f7dedf2887cd3c113b6d8da9cea19e55c1116e25f1f0e1b72d7543179b5939450600360ff198254161790555160018152a280f35b5050509061142a91612438565b80f35b835163818d938f60e01b8152fd5b9097508581813d8311611463575b611453818361201e565b810103126112a2575196896113cc565b503d611449565b85513d8b823e3d90fd5b8351635800797f60e11b8152fd5b8251630627cd6b60e01b81528690fd5b506114a16009820154426121fc565b60065411611365565b845163365105ef60e11b81528890fd5b9091506114cb578814158a82611355565b634e487b7160e01b8a526021895260248afd5b8a92506002811415915061134e565b634e487b7160e01b895260218852602489fd5b50913461031157602090816003193601126103715780356001600160401b039182821161036d573660238301121561036d578181013592831161036d576024903660248585010111610a605785546001600160a01b031633036116c457506115696002546120e8565b601f8111611680575b508490601f84116001146115fd5750918060248697938260809660008051602061274b83398151915299916115f0575b508360011b906000198560031b1c1916176002555b6060600554956006548151998a98895288015286015282606086015201848401378181018301869052601f01601f19168101030190a180f35b83915082010135386115a2565b90601f198416600287528587209287905b82821061166557505060008051602061274b8339815191529697938593849360809760249410611649575b5050600183811b016002556115b7565b8201830135600019600386901b60f8161c191690553880611639565b909293876001819284888a010135815501950193019061160e565b60028652848620601f850160051c8101918686106116ba575b601f0160051c01905b8181106116af5750611572565b8681556001016116a2565b9091508190611699565b865163c383977560e01b8152fd5b5034610311576116e136612162565b6001549092916001600160a01b03918216338190036118a05760028511611890578186526008602052838620549360ff600a61171c876121a4565b500154166007811015610e19576005036118815760207f394027a5fa6e098a1191094d1719d6929b9abc535fcc0c8f448d6a4e756222769151878152a360038260008051602061272b8339815191528680a3611777826121a4565b509281845416908260018601541693600382101561186e57958097816117a18194600a999a612312565b9a929b919690948160028401558160038401558201558260078201558260088201550198600660ff198b5416178a55858115801561184d575b50505050858115801561182c575b5050505080611814575b5050826117fd578480f35b61180b935460081c166126cd565b50388080808480f35b6118249183875460081c166126cd565b5038806117f2565b8392839283928390611844575bf150863885816117e8565b506108fc611839565b8392839283928390611865575bf150813885816117da565b506108fc61185a565b634e487b7160e01b875260218852602487fd5b5163f10068b560e01b81528790fd5b83516309efd47960e41b81528790fd5b8351630955f84760e31b81528790fd5b5082346103715760203660031901126103715760209282913581526008845220549051908152f35b50346103115781600319360112610311576020906007549051908152f35b50346103115781600319360112610311576020905160028152f35b508290602080600319360112610c225782359161192d836121a4565b5093600a85019060ff825416600781101580611ace57600182141580611ae1575b8181611abd575b50611aad57611a9a5760021480611a82575b611a745785546001600160a01b03969087163303611a6557600781019661198f348954612241565b8098556001541696858551809963f7434ea960e01b8252828683015281806119b96024820161224e565b03915afa97881561146a578998611a36575b508711611a275742600982015560080154861115611a19577fc74b9f7dedf2887cd3c113b6d8da9cea19e55c1116e25f1f0e1b72d7543179b594955060ff198254161790555160028152a280f35b505050509061142a91612438565b508251631a48f3db60e11b8152fd5b9097508581813d8311611a5e575b611a4e818361201e565b810103126112a2575196896119cb565b503d611a44565b50825163e2bc376b60e01b8152fd5b8251630627cd6b60e01b8152fd5b50611a916009870154426121fc565b60065411611967565b634e487b7160e01b885260218252602488fd5b845163376af24960e21b81528390fd5b9050611ace57600382141581611955565b634e487b7160e01b895260218352602489fd5b505087600282141561194e565b5060603660031901126103115782356024356001600160401b038111610c2257611b1b9036908601612070565b611b236120bc565b918480526009602052838520543411611be657806005611b416121d9565b5080546001600160a01b0319908116331782556001820180549091166001600160a01b03979097169687179055346002820155600a81018054610100600160a81b03191690550155600754600019810195908611611bd35750602095507f0a7ca50c43ec865fdc8519822762f88432e18409024b9c036d6507b9c8f79d80610a2486928651918291339634908461221f565b634e487b7160e01b815260118752602490fd5b8351631d9c3dff60e31b81528690fd5b503461031157602036600319011261031157823590611c14826121a4565b509060ff600a8301541660078110156108a757600303611dfe57611c3c6009830154426121fc565b60055411610889575091828194600760029501918383549355611c5e856121a4565b50805460018201546001600160a01b039487938493928716928716918491829190611c888d6121a4565b50978e890154838a0154918c600a60088d01549c015460081c161592801515600014611df657925b15611dd857509184611ccf83611cc9600a9584976121fc565b9c612241565b945b600282908401558160038401558201558260078201558260088201550197600660ff198a54161789558581158015611db7575b505050508481158015611d96575b5050505080611d7e575b50508482611d66575b505050508215928315611d4b57505050508060008051602061272b83398151915291a380f35b84938493849354169083906107f057f15082388080806107b9565b611d74935460081c166126cd565b5038808084611d25565b611d8e9187865460081c166126cd565b503880611d1c565b8392839283928390611dae575bf15088388481611d12565b506108fc611da3565b8392839283928390611dcf575bf15081388581611d04565b506108fc611dc4565b999550819398509184611dee600a9382956121fc565b969499611cd1565b508192611cb0565b51635ed7670b60e11b81528490fd5b5090346110fd57806003193601126110fd578151918282600254611e30816120e8565b9081845260209560019187600182169182600014611eb6575050600114611e78575b505050611e749291611e6591038561201e565b51928284938452830190612122565b0390f35b9190869350600283528383205b828410611e9e5750505082010181611e65611e74611e52565b8054848a018601528895508794909301928101611e85565b60ff19168782015293151560051b86019093019350849250611e659150611e749050611e52565b5034610311578160031936011261031157905490516001600160a01b039091168152602090f35b5060803660031901126103115782356024356001600160401b038111610c2257611f319036908601612070565b90611f3a6120bc565b906064359260018060a01b0380851680950361201a57868052600960205285872054341161200a5760058391611f6e6121d9565b508054969091166001600160a01b0319968716811782556001820180549097168817909655346002820155600a81018054610100600160a81b03191690550155600754600019810196908711611ff757506020965085917f0a7ca50c43ec865fdc8519822762f88432e18409024b9c036d6507b9c8f79d8091610a24875192839234908461221f565b634e487b7160e01b815260118852602490fd5b8551631d9c3dff60e31b81528890fd5b8680fd5b90601f801991011681019081106001600160401b0382111761203f57604052565b634e487b7160e01b600052604160045260246000fd5b6001600160401b03811161203f57601f01601f191660200190565b81601f820112156120b75780359061208782612055565b92612095604051948561201e565b828452602083830101116120b757816000926020809301838601378301015290565b600080fd5b604435906001600160a01b03821682036120b757565b608435906001600160a01b03821682036120b757565b90600182811c92168015612118575b602083101461210257565b634e487b7160e01b600052602260045260246000fd5b91607f16916120f7565b919082519283825260005b84811061214e575050826000602080949584010152601f8019910116010190565b60208183018101518483018201520161212d565b60409060031901126120b7576004359060243590565b602435906001600160a01b03821682036120b757565b600435906001600160a01b03821682036120b757565b6007548110156121c3576007600052600b602060002091020190600090565b634e487b7160e01b600052603260045260246000fd5b600754600160401b81101561203f578060016121f892016007556121a4565b9091565b9190820391821161220957565b634e487b7160e01b600052601160045260246000fd5b61223760409295949395606083526060830190612122565b9460208201520152565b9190820180921161220957565b6002546000929161225e826120e8565b908181526020926001906001811690816000146122c35750600114612284575b50505050565b929394509060026000528360002092846000945b8386106122af57505050500101903880808061227e565b805485870183015294019385908201612298565b60ff191685840152505090151560051b010191503880808061227e565b90926122f9606093969594608084526080840190612122565b6001600160a01b03909616602083015260408201520152565b91600092600092838061232582946121a4565b50926002840154936003810154986004820154600783015495600884015493600a60018060a01b0391015460081c1615946003811015612424576001810361239a5750505050506000146123865750610750612382928792612241565b9391565b93925085945094612396916121fc565b9290565b939b5093969591945092916002036123f157505080156123e957925b156123d35750906123ca816123d0936121fc565b95612241565b91565b95945081939250906123e4916121fc565b929190565b5081926123b6565b93985050505060011c8095819060011c926000146124185750906123ca816123d093612241565b93925094508093509290565b634e487b7160e01b82526021600452602482fd5b90612442826121a4565b50600a8101805460ff191660051790556001546040805163c13517e160e01b815260026004820152602481018290526001600160a01b0395602093919290918490849089168189816124966044820161224e565b03925af19283156125ea5760009361259b575b507f8bd32f430ff060e6bd204709b3790c9807987263d3230c580dc80b5f89e27186916060608092600688019580875560005260088752828160002055896001541695549660045490825194855284015282015260006060820152a36007810180549083808311612567575b505050600881019182549281841161252f575b5050505050565b60009460018695948461254588979688976121fc565b945501541682821561255e575bf1503880808080612528565b506108fc612552565b60008093928261257a83959484956121fc565b915587865416828215612592575bf150388083612515565b506108fc612588565b9092508381813d83116125e3575b6125b3818361201e565b810103126120b75751917f8bd32f430ff060e6bd204709b3790c9807987263d3230c580dc80b5f89e271866124a9565b503d6125a9565b50513d6000823e3d90fd5b3d15612620573d9061260682612055565b91612614604051938461201e565b82523d6000602084013e565b606090565b908160209103126120b7575180151581036120b75790565b9060018060a01b039384604051948160208701946323b872dd60e01b865216602487015216604485015260648401526064835260a083018381106001600160401b0382111761203f57600094859485926040525193165af161269d6125f5565b816126a6575090565b80518015925082156126b757505090565b6126ca9250602080918301019101612625565b90565b60405163a9059cbb60e01b602082019081526001600160a01b0393841660248301526044808301959095529381529192608083016001600160401b0381118482101761203f57600094859485926040525193165af161269d6125f556fe89e6168584e1de3ec704ff46376271b5481b0d9b2b0ef0ae102f0d001093e000f0d0a0b363c32316c3e6e7e797bbc126af09c634db439ed65a3f96afe7ae2367d1432ca9a38d944f01b256a411861b109bc4bfe200c40d7144e919a16b86a8a8a26469706673582212205b2f8a11e2887439a1f7713cbd67d4ed2d8739faa61061ca66daa3e5c240117964736f6c63430008180033f0d0a0b363c32316c3e6e7e797bbc126af09c634db439ed65a3f96afe7ae2367", + "deployedBytecode": "0x6040608081526004908136101561001557600080fd5b600090813560e01c8063040c488814611f045780630c340a2414611edd5780630c7ac7b614611e0d5780631bd1823a14611bf65780632a7027de14611aee5780632be6d005146119115780632e0b6422146118f65780632e7700f0146118d85780632fbe3b03146118b0578063311a6c56146116d257806334e2672d146115005780633bf547241461130f578063441080fe146112f15780634660ebbe146112a65780634ab162e2146111465780636cc6cde11461111e5780637aa77f2914611100578063871fbf86146110b857806393ee267814610f305780639ace38c214610e54578063a0af81f014610e2c578063b2b9679214610c44578063b329036b14610c26578063c5d5528814610b11578063cb44c3fa14610ab3578063d2b8ae9c14610a64578063e3f07e9014610904578063e4c0aaf4146108ba578063e77d0bd31461068e578063e98c579b1461061b578063ee22610b146104c7578063ef48eee6146103ac578063f05a59f914610375578063fc548f08146103155763fe43a992146101a257600080fd5b34610311576101b036612162565b9190936101bc856121a4565b5060018101546001600160a01b039391929190841633810361030357600a84019081549060ff821660078110156102f0576102e0576002860190815490818a116102d05785518a81526001600160a01b039091166020820152999a8b9a8995948c949293909291610249918d91869060008051602061276b8339815191529080604081015b0390a26121fc565b809155156102ad575b5050505460081c16801560001461028457505050839283928392541682821561027b575bf15080f35b506108fc610276565b919550939192610296935416906126cd565b156102a057505080f35b5163022e258160e11b8152fd5b60ff1916600617835560008051602061272b8339815191528280a3873880610252565b85516305aafecf60e01b81528790fd5b50505051634e22597f60e11b8152fd5b634e487b7160e01b8a526021865260248afd5b5051635800797f60e11b8152fd5b5080fd5b5082346103715760203660031901126103715780356001600160a01b03818116939184900361036d578454163303610360575050600180546001600160a01b03191691909117905580f35b5163c383977560e01b8152fd5b8480fd5b8280fd5b50346103115760203660031901126103115760209181906001600160a01b0361039c61218e565b1681526009845220549051908152f35b5034610311576103bb36612162565b9190936103c7856121a4565b5080546001600160a01b03939192919084163381036104b957600a84019081549060ff821660078110156102f0576102e0576002860190815490818a116102d05785518a81526001600160a01b039091166020820152999a8b9a8995948c94929390929161044d918d91869060008051602061276b833981519152908060408101610241565b80915515610496575b5050505460081c16801560001461048157505050839283926001849301541682821561027b57f15080f35b919550939192600161029694015416906126cd565b60ff1916600617835560008051602061272b8339815191528280a3873880610456565b505163e2bc376b60e01b8152fd5b509134610311576020366003190112610311578035906104e6826121a4565b506005810154421061060c57600a81019081549260ff841660078110156105f9576105eb576002820180549087905560ff19909416600617928390556001600160a01b039260081c8316806105a857505094826105878388888080808b9a60008051602061276b8339815191529a829f600101541682821561059f575bf1505b5493519283529092166001600160a01b031660208201529081906040820190565b0390a260008051602061272b8339815191528280a380f35b506108fc610563565b846105ba9185600186015416906126cd565b156105dd575094839261058760008051602061276b833981519152938798610566565b865163022e258160e11b8152fd5b8651634e22597f60e11b8152fd5b634e487b7160e01b875260218252602487fd5b5083516302eb354360e41b8152fd5b50829034610371576020366003190112610371578254823592906001600160a01b03163303610680575090606060008051602061274b833981519152928260065560055492815193845260208401528201528061067a6060820161224e565b0390a180f35b905163c383977560e01b8152fd5b5034610311576020366003190112610311578235906106ac826121a4565b509060ff600a8301541660078110156108a7578503610898576106d36009830154426121fc565b600554116108895750918281946008600195019183835493556106f5856121a4565b5091868060a01b039283815416848983015416908788809581956107188d6121a4565b506002810154906003810154998c600a600784015493015460081c161560001461086b575091846107558b610750600a958497612241565b6121fc565b9a945b8160028401558160038401558201558260078201558260088201550197600660ff198a5416178955858115801561084a575b505050508481158015610829575b5050505080610811575b505084826107f9575b5050505082159283156107d2575b505050508060008051602061272b83398151915291a380f35b849384938885940154169083906107f0575bf15082388080806107b9565b506108fc6107e4565b610807935460081c166126cd565b50388080846107ab565b6108219187865460081c166126cd565b5038806107a2565b8392839283928390610841575bf15088388481610798565b506108fc610836565b8392839283928390610862575bf1508138858161078a565b506108fc610857565b9398508995509184610882600a939b82959c6121fc565b9699610758565b51634799187b60e01b81528490fd5b51638225aba560e01b81528490fd5b634e487b7160e01b855260218652602485fd5b50829034610371576020366003190112610371576001600160a01b0382358181169391929084900361036d5784549233908416036103605750506001600160a01b03191617815580f35b50346103115760a0366003190112610311578235610920612178565b604435916064356001600160401b038111610a60576109429036908801612070565b9161094b6120d2565b6001600160a01b038281168852600960205286882054909591908411610a50576109778430338661263d565b15610a4057600582916109886121d9565b5080546001600160a01b0319908116331782556001820180549091169990921698891790915560028101869055600a81018054610100600160a81b031916600887901b610100600160a81b03161790550155600754600019810197908811610a2d575060209750917fb96ca2c0c34e2ad6384277748b8101f4bddc3cbeaad7086e59cd315bd19aa8c591610a24889488519384933398856122e0565b0390a451908152f35b634e487b7160e01b815260118952602490fd5b865163022e258160e11b81528990fd5b8651631d9c3dff60e31b81528990fd5b8580fd5b508234610371578160031936011261037157610a7e61218e565b83546001600160a01b03929083163303610aa5575016825260096020526024359082205580f35b835163c383977560e01b8152fd5b50829034610371576020366003190112610371578254823592906001600160a01b03163303610680575090606060008051602061274b8339815191529282600555600654815193845260208401528201528061067a6060820161224e565b508234610371576003198281360112610c22576001600160401b038235818111610a6057610b429036908501612070565b90602435908111610a6057610b5a9036908501612070565b85549091906001600160a01b039081163303610c125790610bb187602094936003541692610bc08951978896879586946312a6505d60e21b865260608d870152866064870152608060248701526084860190612122565b91848303016044850152612122565b03925af1928315610c0957508392610bd757505580f35b9091506020813d602011610c01575b81610bf36020938361201e565b810103126103715751905580f35b3d9150610be6565b513d85823e3d90fd5b855163c383977560e01b81528590fd5b8380fd5b50346103115781600319360112610311576020906005549051908152f35b503461031157610c5336612162565b610c5e8293926121a4565b50600a8101805460ff8116926007841015610e1957831580610e0b575b610dfb576003841015610deb5788600292838301548711610ddc578690426009850155600196878114600014610d3257505082546001600160a01b031633039150610d22905057600301849055815460ff1916179055905b8251916003811015610d0f577f10c8b22b69e324b0227c6adfa65183c771304c11385423e93ce99779a7483dbf9495965082526020820152a280f35b634e487b7160e01b865260218752602486fd5b855163e2bc376b60e01b81528990fd5b9496949293928703610d75575050808301546001600160a01b03163303610d665701849055815460ff191617905590610cd3565b508551635800797f60e11b8152fd5b8254949694919390916001600160a01b03903390821603610da65750505060030155815460ff191617905590610cd3565b909291935086829795970154163314600014610dcd570185905560ff191617905590610cd3565b50865163351c18ff60e21b8152fd5b5086516305aafecf60e01b8152fd5b8551630d71592960e31b81528990fd5b85516338e5e54b60e21b81528990fd5b506005810154421015610c7b565b634e487b7160e01b885260218952602488fd5b503461031157816003193601126103115760035490516001600160a01b039091168152602090f35b503461031157602036600319011261031157823560075481101561037157610e7b906121a4565b5090600160a01b60019003918281541693836001830154169160028101546003820154888301546005840154600685015491600786015493600887015495600988015497600a01549a60ff8c169a81519e8f908152602001528d015260608c015260808b015260a08a015260c089015260e08801526101008701526101208601526007821015610f1d5750610180945061014084015260081c16610160820152f35b634e487b7160e01b815260218652602490fd5b5082903461037157602036600319011261037157813590610f50826121a4565b50600a81019182549060ff821660078110156110a5576001810361105d575082546001600160a01b0316330361104e575090859185820154915b6006600282019285610f9d8686546121fc565b94556003830186905588830186905560ff19161780865560081c6001600160a01b03908116959092908661101f575084955091600182868080808099979887829a5416828215611016575bf15001541682821561100d575bf1505b60008051602061272b8339815191528380a380f35b506108fc610ff5565b506108fc610fe8565b82949550611038849261104898846001965416906126cd565b505460081c1692015416906126cd565b50610ff8565b5163e2bc376b60e01b81528590fd5b6002036110965760018301546001600160a01b031633036110875750908591600382015491610f8a565b51635800797f60e11b81528590fd5b51630a7b6ec160e01b81528590fd5b634e487b7160e01b885260218752602488fd5b5082346103715781600319360112610371576024359260038410156110fd57506080926110e59135612312565b92939091815194855260208501528301526060820152f35b80fd5b50823461037157826003193601126103715760209250549051908152f35b503461031157816003193601126103115760015490516001600160a01b039091168152602090f35b50346103115760c0366003190112610311578235611162612178565b604435906064356001600160401b038111610a60576111849036908801612070565b61118c6120d2565b9260a4359460018060a01b038087168097036112a25780851689526009602052878920548211611292576111c28230338861263d565b1561128257600583916111d36121d9565b5080546001600160a01b03199081169290991691821781556001810180549099168a1790985560028801849055600a88018054610100600160a81b031916600889901b610100600160a81b031617905596015560075460001981019890891161126f57506020985091610a248894927fb96ca2c0c34e2ad6384277748b8101f4bddc3cbeaad7086e59cd315bd19aa8c5948951948594856122e0565b634e487b7160e01b815260118a52602490fd5b875163022e258160e11b81528a90fd5b8751631d9c3dff60e31b81528a90fd5b8880fd5b5082346103715760203660031901126103715780356001600160a01b03818116939184900361036d578454163303610360575050600380546001600160a01b03191691909117905580f35b50346103115781600319360112610311576020906006549051908152f35b508290602080600319360112610c225782359161132b836121a4565b50600a81019060ff8254166007811015806114ed576001821491821590816114de575b82826114ba575b50506114aa576110a55780611492575b6114825760018101546001600160a01b03969087163303611474576008820196611390348954612241565b8098556001541696858551809963f7434ea960e01b8252828583015281806113ba6024820161224e565b03915afa97881561146a57899861143b575b50871161142d57504260098201556007015485111561141d577fc74b9f7dedf2887cd3c113b6d8da9cea19e55c1116e25f1f0e1b72d7543179b5939450600360ff198254161790555160018152a280f35b5050509061142a91612438565b80f35b835163818d938f60e01b8152fd5b9097508581813d8311611463575b611453818361201e565b810103126112a2575196896113cc565b503d611449565b85513d8b823e3d90fd5b8351635800797f60e11b8152fd5b8251630627cd6b60e01b81528690fd5b506114a16009820154426121fc565b60065411611365565b845163365105ef60e11b81528890fd5b9091506114cb578814158a82611355565b634e487b7160e01b8a526021895260248afd5b8a92506002811415915061134e565b634e487b7160e01b895260218852602489fd5b50913461031157602090816003193601126103715780356001600160401b039182821161036d573660238301121561036d578181013592831161036d576024903660248585010111610a605785546001600160a01b031633036116c457506115696002546120e8565b601f8111611680575b508490601f84116001146115fd5750918060248697938260809660008051602061274b83398151915299916115f0575b508360011b906000198560031b1c1916176002555b6060600554956006548151998a98895288015286015282606086015201848401378181018301869052601f01601f19168101030190a180f35b83915082010135386115a2565b90601f198416600287528587209287905b82821061166557505060008051602061274b8339815191529697938593849360809760249410611649575b5050600183811b016002556115b7565b8201830135600019600386901b60f8161c191690553880611639565b909293876001819284888a010135815501950193019061160e565b60028652848620601f850160051c8101918686106116ba575b601f0160051c01905b8181106116af5750611572565b8681556001016116a2565b9091508190611699565b865163c383977560e01b8152fd5b5034610311576116e136612162565b6001549092916001600160a01b03918216338190036118a05760028511611890578186526008602052838620549360ff600a61171c876121a4565b500154166007811015610e19576005036118815760207f394027a5fa6e098a1191094d1719d6929b9abc535fcc0c8f448d6a4e756222769151878152a360038260008051602061272b8339815191528680a3611777826121a4565b509281845416908260018601541693600382101561186e57958097816117a18194600a999a612312565b9a929b919690948160028401558160038401558201558260078201558260088201550198600660ff198b5416178a55858115801561184d575b50505050858115801561182c575b5050505080611814575b5050826117fd578480f35b61180b935460081c166126cd565b50388080808480f35b6118249183875460081c166126cd565b5038806117f2565b8392839283928390611844575bf150863885816117e8565b506108fc611839565b8392839283928390611865575bf150813885816117da565b506108fc61185a565b634e487b7160e01b875260218852602487fd5b5163f10068b560e01b81528790fd5b83516309efd47960e41b81528790fd5b8351630955f84760e31b81528790fd5b5082346103715760203660031901126103715760209282913581526008845220549051908152f35b50346103115781600319360112610311576020906007549051908152f35b50346103115781600319360112610311576020905160028152f35b508290602080600319360112610c225782359161192d836121a4565b5093600a85019060ff825416600781101580611ace57600182141580611ae1575b8181611abd575b50611aad57611a9a5760021480611a82575b611a745785546001600160a01b03969087163303611a6557600781019661198f348954612241565b8098556001541696858551809963f7434ea960e01b8252828683015281806119b96024820161224e565b03915afa97881561146a578998611a36575b508711611a275742600982015560080154861115611a19577fc74b9f7dedf2887cd3c113b6d8da9cea19e55c1116e25f1f0e1b72d7543179b594955060ff198254161790555160028152a280f35b505050509061142a91612438565b508251631a48f3db60e11b8152fd5b9097508581813d8311611a5e575b611a4e818361201e565b810103126112a2575196896119cb565b503d611a44565b50825163e2bc376b60e01b8152fd5b8251630627cd6b60e01b8152fd5b50611a916009870154426121fc565b60065411611967565b634e487b7160e01b885260218252602488fd5b845163376af24960e21b81528390fd5b9050611ace57600382141581611955565b634e487b7160e01b895260218352602489fd5b505087600282141561194e565b5060603660031901126103115782356024356001600160401b038111610c2257611b1b9036908601612070565b611b236120bc565b918480526009602052838520543411611be657806005611b416121d9565b5080546001600160a01b0319908116331782556001820180549091166001600160a01b03979097169687179055346002820155600a81018054610100600160a81b03191690550155600754600019810195908611611bd35750602095507f0a7ca50c43ec865fdc8519822762f88432e18409024b9c036d6507b9c8f79d80610a2486928651918291339634908461221f565b634e487b7160e01b815260118752602490fd5b8351631d9c3dff60e31b81528690fd5b503461031157602036600319011261031157823590611c14826121a4565b509060ff600a8301541660078110156108a757600303611dfe57611c3c6009830154426121fc565b60055411610889575091828194600760029501918383549355611c5e856121a4565b50805460018201546001600160a01b039487938493928716928716918491829190611c888d6121a4565b50978e890154838a0154918c600a60088d01549c015460081c161592801515600014611df657925b15611dd857509184611ccf83611cc9600a9584976121fc565b9c612241565b945b600282908401558160038401558201558260078201558260088201550197600660ff198a54161789558581158015611db7575b505050508481158015611d96575b5050505080611d7e575b50508482611d66575b505050508215928315611d4b57505050508060008051602061272b83398151915291a380f35b84938493849354169083906107f057f15082388080806107b9565b611d74935460081c166126cd565b5038808084611d25565b611d8e9187865460081c166126cd565b503880611d1c565b8392839283928390611dae575bf15088388481611d12565b506108fc611da3565b8392839283928390611dcf575bf15081388581611d04565b506108fc611dc4565b999550819398509184611dee600a9382956121fc565b969499611cd1565b508192611cb0565b51635ed7670b60e11b81528490fd5b5090346110fd57806003193601126110fd578151918282600254611e30816120e8565b9081845260209560019187600182169182600014611eb6575050600114611e78575b505050611e749291611e6591038561201e565b51928284938452830190612122565b0390f35b9190869350600283528383205b828410611e9e5750505082010181611e65611e74611e52565b8054848a018601528895508794909301928101611e85565b60ff19168782015293151560051b86019093019350849250611e659150611e749050611e52565b5034610311578160031936011261031157905490516001600160a01b039091168152602090f35b5060803660031901126103115782356024356001600160401b038111610c2257611f319036908601612070565b90611f3a6120bc565b906064359260018060a01b0380851680950361201a57868052600960205285872054341161200a5760058391611f6e6121d9565b508054969091166001600160a01b0319968716811782556001820180549097168817909655346002820155600a81018054610100600160a81b03191690550155600754600019810196908711611ff757506020965085917f0a7ca50c43ec865fdc8519822762f88432e18409024b9c036d6507b9c8f79d8091610a24875192839234908461221f565b634e487b7160e01b815260118852602490fd5b8551631d9c3dff60e31b81528890fd5b8680fd5b90601f801991011681019081106001600160401b0382111761203f57604052565b634e487b7160e01b600052604160045260246000fd5b6001600160401b03811161203f57601f01601f191660200190565b81601f820112156120b75780359061208782612055565b92612095604051948561201e565b828452602083830101116120b757816000926020809301838601378301015290565b600080fd5b604435906001600160a01b03821682036120b757565b608435906001600160a01b03821682036120b757565b90600182811c92168015612118575b602083101461210257565b634e487b7160e01b600052602260045260246000fd5b91607f16916120f7565b919082519283825260005b84811061214e575050826000602080949584010152601f8019910116010190565b60208183018101518483018201520161212d565b60409060031901126120b7576004359060243590565b602435906001600160a01b03821682036120b757565b600435906001600160a01b03821682036120b757565b6007548110156121c3576007600052600b602060002091020190600090565b634e487b7160e01b600052603260045260246000fd5b600754600160401b81101561203f578060016121f892016007556121a4565b9091565b9190820391821161220957565b634e487b7160e01b600052601160045260246000fd5b61223760409295949395606083526060830190612122565b9460208201520152565b9190820180921161220957565b6002546000929161225e826120e8565b908181526020926001906001811690816000146122c35750600114612284575b50505050565b929394509060026000528360002092846000945b8386106122af57505050500101903880808061227e565b805485870183015294019385908201612298565b60ff191685840152505090151560051b010191503880808061227e565b90926122f9606093969594608084526080840190612122565b6001600160a01b03909616602083015260408201520152565b91600092600092838061232582946121a4565b50926002840154936003810154986004820154600783015495600884015493600a60018060a01b0391015460081c1615946003811015612424576001810361239a5750505050506000146123865750610750612382928792612241565b9391565b93925085945094612396916121fc565b9290565b939b5093969591945092916002036123f157505080156123e957925b156123d35750906123ca816123d0936121fc565b95612241565b91565b95945081939250906123e4916121fc565b929190565b5081926123b6565b93985050505060011c8095819060011c926000146124185750906123ca816123d093612241565b93925094508093509290565b634e487b7160e01b82526021600452602482fd5b90612442826121a4565b50600a8101805460ff191660051790556001546040805163c13517e160e01b815260026004820152602481018290526001600160a01b0395602093919290918490849089168189816124966044820161224e565b03925af19283156125ea5760009361259b575b507f8bd32f430ff060e6bd204709b3790c9807987263d3230c580dc80b5f89e27186916060608092600688019580875560005260088752828160002055896001541695549660045490825194855284015282015260006060820152a36007810180549083808311612567575b505050600881019182549281841161252f575b5050505050565b60009460018695948461254588979688976121fc565b945501541682821561255e575bf1503880808080612528565b506108fc612552565b60008093928261257a83959484956121fc565b915587865416828215612592575bf150388083612515565b506108fc612588565b9092508381813d83116125e3575b6125b3818361201e565b810103126120b75751917f8bd32f430ff060e6bd204709b3790c9807987263d3230c580dc80b5f89e271866124a9565b503d6125a9565b50513d6000823e3d90fd5b3d15612620573d9061260682612055565b91612614604051938461201e565b82523d6000602084013e565b606090565b908160209103126120b7575180151581036120b75790565b9060018060a01b039384604051948160208701946323b872dd60e01b865216602487015216604485015260648401526064835260a083018381106001600160401b0382111761203f57600094859485926040525193165af161269d6125f5565b816126a6575090565b80518015925082156126b757505090565b6126ca9250602080918301019101612625565b90565b60405163a9059cbb60e01b602082019081526001600160a01b0393841660248301526044808301959095529381529192608083016001600160401b0381118482101761203f57600094859485926040525193165af161269d6125f556fe89e6168584e1de3ec704ff46376271b5481b0d9b2b0ef0ae102f0d001093e000f0d0a0b363c32316c3e6e7e797bbc126af09c634db439ed65a3f96afe7ae2367d1432ca9a38d944f01b256a411861b109bc4bfe200c40d7144e919a16b86a8a8a26469706673582212205b2f8a11e2887439a1f7713cbd67d4ed2d8739faa61061ca66daa3e5c240117964736f6c63430008180033", + "devdoc": { + "details": "Version of Escrow that allows to specify a buyer when transaction is created.", + "events": { + "DisputeRequest(address,uint256,uint256,uint256,string)": { + "details": "To be emitted when a dispute is created to link the correct meta-evidence to the disputeID.", + "params": { + "_arbitrator": "The arbitrator of the contract.", + "_arbitratorDisputeID": "The identifier of the dispute in the Arbitrator contract.", + "_externalDisputeID": "An identifier created outside Kleros by the protocol requesting arbitration.", + "_templateId": "The identifier of the dispute template. Should not be used with _templateUri.", + "_templateUri": "The URI to the dispute template. For example on IPFS: starting with '/ipfs/'. Should not be used with _templateId." + } + }, + "ERC20TransactionCreated(uint256,string,address,address,address,uint256,uint256)": { + "details": "Emitted when a transaction paid in ERC20 token is created.", + "params": { + "_amount": "The initial amount in the transaction.", + "_buyer": "The address of the buyer.", + "_deadline": "The deadline of the transaction.", + "_seller": "The address of the seller.", + "_token": "The token address.", + "_transactionID": "The index of the transaction.", + "_transactionUri": "The IPFS Uri Hash of the transaction." + } + }, + "HasToPayFee(uint256,uint8)": { + "details": "Indicate that a party has to pay a fee or would otherwise be considered as losing.", + "params": { + "_party": "The party who has to pay.", + "_transactionID": "The index of the transaction." + } + }, + "NativeTransactionCreated(uint256,string,address,address,uint256,uint256)": { + "details": "Emitted when a transaction paid in native currency is created.", + "params": { + "_amount": "The initial amount in the transaction.", + "_buyer": "The address of the buyer.", + "_deadline": "The deadline of the transaction.", + "_seller": "The address of the seller.", + "_transactionID": "The index of the transaction.", + "_transactionUri": "The IPFS Uri Hash of the transaction." + } + }, + "ParameterUpdated(uint256,uint256,bytes)": { + "details": "To be emitted when Escrow parameters are updated." + }, + "Payment(uint256,uint256,address)": { + "details": "To be emitted when a party pays or reimburses the other.", + "params": { + "_amount": "The amount paid.", + "_party": "The party that paid.", + "_transactionID": "The index of the transaction." + } + }, + "Ruling(address,uint256,uint256)": { + "details": "To be raised when a ruling is given.", + "params": { + "_arbitrator": "The arbitrator giving the ruling.", + "_disputeID": "The identifier of the dispute in the Arbitrator contract.", + "_ruling": "The ruling which was given." + } + }, + "SettlementProposed(uint256,uint8,uint256)": { + "details": "Emitted when a party proposes a settlement.", + "params": { + "_amount": "The amount proposed.", + "_party": "The party that proposed a settlement.", + "_transactionID": "The index of the transaction." + } + }, + "TransactionResolved(uint256,uint8)": { + "details": "To be emitted when a transaction is resolved, either by its execution, a timeout or because a ruling was enforced.", + "params": { + "_resolution": "Short description of what caused the transaction to be solved.", + "_transactionID": "The ID of the respective transaction." + } + } + }, + "kind": "dev", + "methods": { + "acceptSettlement(uint256)": { + "details": "Accept a settlement proposed by the other party.", + "params": { + "_transactionID": "The index of the transaction." + } + }, + "constructor": { + "details": "Constructor.", + "params": { + "_arbitrator": "The arbitrator of the contract.", + "_arbitratorExtraData": "Extra data for the arbitrator.", + "_feeTimeout": "Arbitration fee timeout for the parties.", + "_settlementTimeout": "Settlement timeout for the parties.", + "_templateData": "The dispute template data.", + "_templateDataMappings": "The dispute template data mappings.", + "_templateRegistry": "The dispute template registry." + } + }, + "createERC20Transaction(uint256,address,uint256,string,address)": { + "details": "Create a transaction.", + "params": { + "_amount": "The amount of tokens in this transaction.", + "_deadline": "Time after which a party can automatically execute the arbitrable transaction.", + "_seller": "The recipient of the transaction.", + "_token": "The ERC20 token contract.", + "_transactionUri": "The IPFS Uri Hash of the transaction." + }, + "returns": { + "transactionID": "The index of the transaction." + } + }, + "createERC20TransactionCustomBuyer(uint256,address,uint256,string,address,address)": { + "details": "Create an ERC20 transaction with custom buyer address.", + "params": { + "_amount": "The amount of tokens in this transaction.", + "_buyer": "Buyer's address.", + "_deadline": "Time after which a party can automatically execute the arbitrable transaction.", + "_seller": "The recipient of the transaction.", + "_token": "The ERC20 token contract.", + "_transactionUri": "The IPFS Uri Hash of the transaction." + }, + "returns": { + "transactionID": "The index of the transaction." + } + }, + "createNativeTransaction(uint256,string,address)": { + "details": "Create a transaction.", + "params": { + "_deadline": "Time after which a party can automatically execute the arbitrable transaction.", + "_seller": "The recipient of the transaction.", + "_transactionUri": "The IPFS Uri Hash of the transaction." + }, + "returns": { + "transactionID": "The index of the transaction." + } + }, + "createNativeTransactionCustomBuyer(uint256,string,address,address)": { + "details": "Create a native transaction with custom buyer.", + "params": { + "_buyer": "Buyer's address.", + "_deadline": "Time after which a party can automatically execute the arbitrable transaction.", + "_seller": "The recipient of the transaction.", + "_transactionUri": "The IPFS Uri Hash of the transaction." + }, + "returns": { + "transactionID": "The index of the transaction." + } + }, + "executeTransaction(uint256)": { + "details": "Transfer the transaction's amount to the seller if the timeout has passed.", + "params": { + "_transactionID": "The index of the transaction." + } + }, + "getPayouts(uint256,uint8)": { + "details": "Get the payout depending on the winning party.The cost for the buyer is the seller payout non-inclusive of any arbitration fees.", + "params": { + "_transactionID": "The index of the transaction.", + "_winningParty": "The winning party." + }, + "returns": { + "buyerPayout": "The payout for the buyer.", + "buyerPayoutToken": "The payout for the buyer in tokens.", + "sellerPayout": "The payout for the seller.", + "sellerPayoutToken": "The payout for the seller in tokens." + } + }, + "getTransactionCount()": { + "details": "Getter to know the count of transactions.", + "returns": { + "_0": "The count of transactions." + } + }, + "pay(uint256,uint256)": { + "details": "Pay seller. To be called if the good or service is provided.", + "params": { + "_amount": "Amount to pay in wei.", + "_transactionID": "The index of the transaction." + } + }, + "payArbitrationFeeByBuyer(uint256)": { + "details": "Pay the arbitration fee to raise a dispute. To be called by the buyer. Note that it can only be called after settlement proposition. Also note that the arbitrator can have createDispute throw, which will make this function throw and therefore lead to a party being timed-out. This is not a vulnerability as the arbitrator can rule in favor of one party anyway.", + "params": { + "_transactionID": "The index of the transaction." + } + }, + "payArbitrationFeeBySeller(uint256)": { + "details": "Pay the arbitration fee to raise a dispute. To be called by the seller. Note that this function mirrors payArbitrationFeeByBuyer.", + "params": { + "_transactionID": "The index of the transaction." + } + }, + "proposeSettlement(uint256,uint256)": { + "details": "Propose a settlement as a compromise from the initial terms to the other party. Note that a party can only propose a settlement again after the other party has done so as well to prevent front running/griefing issues.", + "params": { + "_amount": "The settlement amount.", + "_transactionID": "The index of the transaction." + } + }, + "reimburse(uint256,uint256)": { + "details": "Reimburse buyer. To be called if the good or service can't be fully provided.", + "params": { + "_amountReimbursed": "Amount to reimburse in wei.", + "_transactionID": "The index of the transaction." + } + }, + "rule(uint256,uint256)": { + "details": "Give a ruling for a dispute. Must be called by the arbitrator. The purpose of this function is to ensure that the address calling it has the right to rule on the contract.", + "params": { + "_disputeID": "The identifier of the dispute in the Arbitrator contract.", + "_ruling": "Ruling given by the arbitrator. Note that 0 is reserved for \"Not able/wanting to make a decision\"." + } + }, + "timeOutByBuyer(uint256)": { + "details": "Reimburse buyer if seller fails to pay the fee.", + "params": { + "_transactionID": "The index of the transaction." + } + }, + "timeOutBySeller(uint256)": { + "details": "Pay seller if buyer fails to pay the fee.", + "params": { + "_transactionID": "The index of the transaction." + } + } + }, + "title": "EscrowCustomBuyer.", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 480, + "contract": "src/EscrowCustomBuyer.sol:EscrowCustomBuyer", + "label": "governor", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 483, + "contract": "src/EscrowCustomBuyer.sol:EscrowCustomBuyer", + "label": "arbitrator", + "offset": 0, + "slot": "1", + "type": "t_contract(IArbitratorV2)134" + }, + { + "astId": 485, + "contract": "src/EscrowCustomBuyer.sol:EscrowCustomBuyer", + "label": "arbitratorExtraData", + "offset": 0, + "slot": "2", + "type": "t_bytes_storage" + }, + { + "astId": 488, + "contract": "src/EscrowCustomBuyer.sol:EscrowCustomBuyer", + "label": "templateRegistry", + "offset": 0, + "slot": "3", + "type": "t_contract(IDisputeTemplateRegistry)160" + }, + { + "astId": 490, + "contract": "src/EscrowCustomBuyer.sol:EscrowCustomBuyer", + "label": "templateId", + "offset": 0, + "slot": "4", + "type": "t_uint256" + }, + { + "astId": 492, + "contract": "src/EscrowCustomBuyer.sol:EscrowCustomBuyer", + "label": "feeTimeout", + "offset": 0, + "slot": "5", + "type": "t_uint256" + }, + { + "astId": 494, + "contract": "src/EscrowCustomBuyer.sol:EscrowCustomBuyer", + "label": "settlementTimeout", + "offset": 0, + "slot": "6", + "type": "t_uint256" + }, + { + "astId": 498, + "contract": "src/EscrowCustomBuyer.sol:EscrowCustomBuyer", + "label": "transactions", + "offset": 0, + "slot": "7", + "type": "t_array(t_struct(Transaction)2688_storage)dyn_storage" + }, + { + "astId": 502, + "contract": "src/EscrowCustomBuyer.sol:EscrowCustomBuyer", + "label": "disputeIDtoTransactionID", + "offset": 0, + "slot": "8", + "type": "t_mapping(t_uint256,t_uint256)" + }, + { + "astId": 507, + "contract": "src/EscrowCustomBuyer.sol:EscrowCustomBuyer", + "label": "amountCaps", + "offset": 0, + "slot": "9", + "type": "t_mapping(t_contract(IERC20)238,t_uint256)" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_address_payable": { + "encoding": "inplace", + "label": "address payable", + "numberOfBytes": "20" + }, + "t_array(t_struct(Transaction)2688_storage)dyn_storage": { + "base": "t_struct(Transaction)2688_storage", + "encoding": "dynamic_array", + "label": "struct Transaction[]", + "numberOfBytes": "32" + }, + "t_bytes_storage": { + "encoding": "bytes", + "label": "bytes", + "numberOfBytes": "32" + }, + "t_contract(IArbitratorV2)134": { + "encoding": "inplace", + "label": "contract IArbitratorV2", + "numberOfBytes": "20" + }, + "t_contract(IDisputeTemplateRegistry)160": { + "encoding": "inplace", + "label": "contract IDisputeTemplateRegistry", + "numberOfBytes": "20" + }, + "t_contract(IERC20)238": { + "encoding": "inplace", + "label": "contract IERC20", + "numberOfBytes": "20" + }, + "t_enum(Status)2655": { + "encoding": "inplace", + "label": "enum Status", + "numberOfBytes": "1" + }, + "t_mapping(t_contract(IERC20)238,t_uint256)": { + "encoding": "mapping", + "key": "t_contract(IERC20)238", + "label": "mapping(contract IERC20 => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_mapping(t_uint256,t_uint256)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_struct(Transaction)2688_storage": { + "encoding": "inplace", + "label": "struct Transaction", + "members": [ + { + "astId": 2663, + "contract": "src/EscrowCustomBuyer.sol:EscrowCustomBuyer", + "label": "buyer", + "offset": 0, + "slot": "0", + "type": "t_address_payable" + }, + { + "astId": 2665, + "contract": "src/EscrowCustomBuyer.sol:EscrowCustomBuyer", + "label": "seller", + "offset": 0, + "slot": "1", + "type": "t_address_payable" + }, + { + "astId": 2667, + "contract": "src/EscrowCustomBuyer.sol:EscrowCustomBuyer", + "label": "amount", + "offset": 0, + "slot": "2", + "type": "t_uint256" + }, + { + "astId": 2669, + "contract": "src/EscrowCustomBuyer.sol:EscrowCustomBuyer", + "label": "settlementBuyer", + "offset": 0, + "slot": "3", + "type": "t_uint256" + }, + { + "astId": 2671, + "contract": "src/EscrowCustomBuyer.sol:EscrowCustomBuyer", + "label": "settlementSeller", + "offset": 0, + "slot": "4", + "type": "t_uint256" + }, + { + "astId": 2673, + "contract": "src/EscrowCustomBuyer.sol:EscrowCustomBuyer", + "label": "deadline", + "offset": 0, + "slot": "5", + "type": "t_uint256" + }, + { + "astId": 2675, + "contract": "src/EscrowCustomBuyer.sol:EscrowCustomBuyer", + "label": "disputeID", + "offset": 0, + "slot": "6", + "type": "t_uint256" + }, + { + "astId": 2677, + "contract": "src/EscrowCustomBuyer.sol:EscrowCustomBuyer", + "label": "buyerFee", + "offset": 0, + "slot": "7", + "type": "t_uint256" + }, + { + "astId": 2679, + "contract": "src/EscrowCustomBuyer.sol:EscrowCustomBuyer", + "label": "sellerFee", + "offset": 0, + "slot": "8", + "type": "t_uint256" + }, + { + "astId": 2681, + "contract": "src/EscrowCustomBuyer.sol:EscrowCustomBuyer", + "label": "lastFeePaymentTime", + "offset": 0, + "slot": "9", + "type": "t_uint256" + }, + { + "astId": 2684, + "contract": "src/EscrowCustomBuyer.sol:EscrowCustomBuyer", + "label": "status", + "offset": 0, + "slot": "10", + "type": "t_enum(Status)2655" + }, + { + "astId": 2687, + "contract": "src/EscrowCustomBuyer.sol:EscrowCustomBuyer", + "label": "token", + "offset": 1, + "slot": "10", + "type": "t_contract(IERC20)238" + } + ], + "numberOfBytes": "352" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} \ No newline at end of file diff --git a/contracts/deployments/arbitrumSepoliaDevnet/EscrowViewCustomBuyer.json b/contracts/deployments/arbitrumSepoliaDevnet/EscrowViewCustomBuyer.json new file mode 100644 index 0000000..3ea92ce --- /dev/null +++ b/contracts/deployments/arbitrumSepoliaDevnet/EscrowViewCustomBuyer.json @@ -0,0 +1,184 @@ +{ + "address": "0xe0892815E8958f0ad6Dab876995987c4F439954D", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_escrow", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "escrow", + "outputs": [ + { + "internalType": "contract EscrowUniversal", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_amountWei", + "type": "uint256" + } + ], + "name": "formatEth", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_amountWei", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_token", + "type": "address" + } + ], + "name": "formatToken", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_transactionID", + "type": "uint256" + } + ], + "name": "getPayoutMessages", + "outputs": [ + { + "internalType": "string", + "name": "noWinner", + "type": "string" + }, + { + "internalType": "string", + "name": "buyerWins", + "type": "string" + }, + { + "internalType": "string", + "name": "sellerWins", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0x62e1160a846fc92ff6016a7a97e5986e381d0eb63cfc965bbac65a780a2c1816", + "receipt": { + "to": null, + "from": "0xf1C7c037891525E360C59f708739Ac09A7670c59", + "contractAddress": "0xe0892815E8958f0ad6Dab876995987c4F439954D", + "transactionIndex": 7, + "gasUsed": "933482", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xd96ea0b3c2426f61283b71c48a2cc2b07f5fae018246be533c69bc0cb72d3827", + "transactionHash": "0x62e1160a846fc92ff6016a7a97e5986e381d0eb63cfc965bbac65a780a2c1816", + "logs": [], + "blockNumber": 177253537, + "cumulativeGasUsed": "1905382", + "status": 1, + "byzantium": true + }, + "args": [ + "0xA01e6B988aeDae1fD4a748D6bfBcB8A438601DeE" + ], + "numDeployments": 1, + "solcInputHash": "fe44112fe2a6f4052d131ccb295c8261", + "metadata": "{\"compiler\":{\"version\":\"0.8.24+commit.e11b9ed9\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_escrow\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"escrow\",\"outputs\":[{\"internalType\":\"contract EscrowUniversal\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amountWei\",\"type\":\"uint256\"}],\"name\":\"formatEth\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amountWei\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"}],\"name\":\"formatToken\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_transactionID\",\"type\":\"uint256\"}],\"name\":\"getPayoutMessages\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"noWinner\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"buyerWins\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"sellerWins\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"constructor\":{\"params\":{\"_escrow\":\"The address of the EscrowUniversal contract.\"}},\"formatEth(uint256)\":{\"params\":{\"_amountWei\":\"The amount in wei.\"},\"returns\":{\"_0\":\"The formatted amount.\"}},\"formatToken(uint256,address)\":{\"params\":{\"_amountWei\":\"The amount in wei.\",\"_token\":\"The address of the token.\"},\"returns\":{\"_0\":\"The formatted amount.\"}},\"getPayoutMessages(uint256)\":{\"returns\":{\"buyerWins\":\"The payout message for the case where the buyer wins.\",\"noWinner\":\"The payout message for the case where nobody wins.\",\"sellerWins\":\"The payout message for the case where the seller wins.\"}}},\"title\":\"EscrowView\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"constructor\":{\"notice\":\"Initialize the view contract with the address of the EscrowUniversal contract.\"},\"formatEth(uint256)\":{\"notice\":\"Format an amount in ETH to 3 decimal places.\"},\"formatToken(uint256,address)\":{\"notice\":\"Format an amount in a token to 3 decimal places.\"},\"getPayoutMessages(uint256)\":{\"notice\":\"Get the payout messages for a transaction *once* a dispute is created.The amounts are exclusive of arbitration fees for clarity.The amounts pre-dispute are imprecise as the arbitration fees are not paid yet by either or both parties.\"}},\"notice\":\"A view contract for EscrowUniversal to facilitate the display of ruling options.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/EscrowView.sol\":\"EscrowView\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":100},\"remappings\":[],\"viaIR\":true},\"sources\":{\"@kleros/kleros-v2-contracts/arbitration/interfaces/IArbitrableV2.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.24;\\n\\nimport \\\"./IArbitratorV2.sol\\\";\\n\\n/// @title IArbitrableV2\\n/// @notice Arbitrable interface.\\n/// @dev When developing arbitrable contracts, we need to:\\n/// - Define the action taken when a ruling is received by the contract.\\n/// - Allow dispute creation. For this a function must call arbitrator.createDispute{value: _fee}(_choices,_extraData);\\ninterface IArbitrableV2 {\\n /// @dev To be emitted when a dispute is created to link the correct meta-evidence to the disputeID.\\n /// @param _arbitrator The arbitrator of the contract.\\n /// @param _arbitratorDisputeID The identifier of the dispute in the Arbitrator contract.\\n /// @param _externalDisputeID An identifier created outside Kleros by the protocol requesting arbitration.\\n /// @param _templateId The identifier of the dispute template. Should not be used with _templateUri.\\n /// @param _templateUri The URI to the dispute template. For example on IPFS: starting with '/ipfs/'. Should not be used with _templateId.\\n event DisputeRequest(\\n IArbitratorV2 indexed _arbitrator,\\n uint256 indexed _arbitratorDisputeID,\\n uint256 _externalDisputeID,\\n uint256 _templateId,\\n string _templateUri\\n );\\n\\n /// @dev To be raised when a ruling is given.\\n /// @param _arbitrator The arbitrator giving the ruling.\\n /// @param _disputeID The identifier of the dispute in the Arbitrator contract.\\n /// @param _ruling The ruling which was given.\\n event Ruling(IArbitratorV2 indexed _arbitrator, uint256 indexed _disputeID, uint256 _ruling);\\n\\n /// @dev Give a ruling for a dispute.\\n /// Must be called by the arbitrator.\\n /// The purpose of this function is to ensure that the address calling it has the right to rule on the contract.\\n /// @param _disputeID The identifier of the dispute in the Arbitrator contract.\\n /// @param _ruling Ruling given by the arbitrator.\\n /// Note that 0 is reserved for \\\"Not able/wanting to make a decision\\\".\\n function rule(uint256 _disputeID, uint256 _ruling) external;\\n}\\n\",\"keccak256\":\"0x054fd09cc201ddca3d92a07169fb86b9db21a510a2a0f15ac4b6dffd900079fe\",\"license\":\"MIT\"},\"@kleros/kleros-v2-contracts/arbitration/interfaces/IArbitratorV2.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.24;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"./IArbitrableV2.sol\\\";\\n\\n/// @title Arbitrator\\n/// Arbitrator interface that implements the new arbitration standard.\\n/// Unlike the ERC-792 this standard is not concerned with appeals, so each arbitrator can implement an appeal system that suits it the most.\\n/// When developing arbitrator contracts we need to:\\n/// - Define the functions for dispute creation (createDispute). Don't forget to store the arbitrated contract and the disputeID (which should be unique, may nbDisputes).\\n/// - Define the functions for cost display (arbitrationCost).\\n/// - Allow giving rulings. For this a function must call arbitrable.rule(disputeID, ruling).\\ninterface IArbitratorV2 {\\n /// @dev To be emitted when a dispute is created.\\n /// @param _disputeID The identifier of the dispute in the Arbitrator contract.\\n /// @param _arbitrable The contract which created the dispute.\\n event DisputeCreation(uint256 indexed _disputeID, IArbitrableV2 indexed _arbitrable);\\n\\n /// @dev To be raised when a ruling is given.\\n /// @param _arbitrable The arbitrable receiving the ruling.\\n /// @param _disputeID The identifier of the dispute in the Arbitrator contract.\\n /// @param _ruling The ruling which was given.\\n event Ruling(IArbitrableV2 indexed _arbitrable, uint256 indexed _disputeID, uint256 _ruling);\\n\\n /// @dev To be emitted when an ERC20 token is added or removed as a method to pay fees.\\n /// @param _token The ERC20 token.\\n /// @param _accepted Whether the token is accepted or not.\\n event AcceptedFeeToken(IERC20 indexed _token, bool indexed _accepted);\\n\\n /// @dev To be emitted when the fee for a particular ERC20 token is updated.\\n /// @param _feeToken The ERC20 token.\\n /// @param _rateInEth The new rate of the fee token in ETH.\\n /// @param _rateDecimals The new decimals of the fee token rate.\\n event NewCurrencyRate(IERC20 indexed _feeToken, uint64 _rateInEth, uint8 _rateDecimals);\\n\\n /// @dev Create a dispute and pay for the fees in the native currency, typically ETH.\\n /// Must be called by the arbitrable contract.\\n /// Must pay at least arbitrationCost(_extraData).\\n /// @param _numberOfChoices The number of choices the arbitrator can choose from in this dispute.\\n /// @param _extraData Additional info about the dispute. We use it to pass the ID of the dispute's court (first 32 bytes), the minimum number of jurors required (next 32 bytes) and the ID of the specific dispute kit (last 32 bytes).\\n /// @return disputeID The identifier of the dispute created.\\n function createDispute(\\n uint256 _numberOfChoices,\\n bytes calldata _extraData\\n ) external payable returns (uint256 disputeID);\\n\\n /// @dev Create a dispute and pay for the fees in a supported ERC20 token.\\n /// Must be called by the arbitrable contract.\\n /// Must pay at least arbitrationCost(_extraData).\\n /// @param _numberOfChoices The number of choices the arbitrator can choose from in this dispute.\\n /// @param _extraData Additional info about the dispute. We use it to pass the ID of the dispute's court (first 32 bytes), the minimum number of jurors required (next 32 bytes) and the ID of the specific dispute kit (last 32 bytes).\\n /// @param _feeToken The ERC20 token used to pay fees.\\n /// @param _feeAmount Amount of the ERC20 token used to pay fees.\\n /// @return disputeID The identifier of the dispute created.\\n function createDispute(\\n uint256 _numberOfChoices,\\n bytes calldata _extraData,\\n IERC20 _feeToken,\\n uint256 _feeAmount\\n ) external returns (uint256 disputeID);\\n\\n /// @dev Compute the cost of arbitration denominated in the native currency, typically ETH.\\n /// It is recommended not to increase it often, as it can be highly time and gas consuming for the arbitrated contracts to cope with fee augmentation.\\n /// @param _extraData Additional info about the dispute. We use it to pass the ID of the dispute's court (first 32 bytes), the minimum number of jurors required (next 32 bytes) and the ID of the specific dispute kit (last 32 bytes).\\n /// @return cost The arbitration cost in ETH.\\n function arbitrationCost(bytes calldata _extraData) external view returns (uint256 cost);\\n\\n /// @dev Compute the cost of arbitration denominated in `_feeToken`.\\n /// It is recommended not to increase it often, as it can be highly time and gas consuming for the arbitrated contracts to cope with fee augmentation.\\n /// @param _extraData Additional info about the dispute. We use it to pass the ID of the dispute's court (first 32 bytes), the minimum number of jurors required (next 32 bytes) and the ID of the specific dispute kit (last 32 bytes).\\n /// @param _feeToken The ERC20 token used to pay fees.\\n /// @return cost The arbitration cost in `_feeToken`.\\n function arbitrationCost(bytes calldata _extraData, IERC20 _feeToken) external view returns (uint256 cost);\\n\\n /// @dev Gets the current ruling of a specified dispute.\\n /// @param _disputeID The ID of the dispute.\\n /// @return ruling The current ruling.\\n /// @return tied Whether it's a tie or not.\\n /// @return overridden Whether the ruling was overridden by appeal funding or not.\\n function currentRuling(uint256 _disputeID) external view returns (uint256 ruling, bool tied, bool overridden);\\n}\\n\",\"keccak256\":\"0xfc7cc82c1431720da41aeb1a181171f10466b5d0d280db7aa37c451681185493\",\"license\":\"MIT\"},\"@kleros/kleros-v2-contracts/arbitration/interfaces/IDisputeTemplateRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.24;\\n\\n/// @title IDisputeTemplate\\n/// @notice Dispute Template interface.\\ninterface IDisputeTemplateRegistry {\\n /// @dev To be emitted when a new dispute template is created.\\n /// @param _templateId The identifier of the dispute template.\\n /// @param _templateTag An optional tag for the dispute template, such as \\\"registration\\\" or \\\"removal\\\".\\n /// @param _templateData The template data.\\n /// @param _templateDataMappings The data mappings.\\n event DisputeTemplate(\\n uint256 indexed _templateId,\\n string indexed _templateTag,\\n string _templateData,\\n string _templateDataMappings\\n );\\n\\n function setDisputeTemplate(\\n string memory _templateTag,\\n string memory _templateData,\\n string memory _templateDataMappings\\n ) external returns (uint256 templateId);\\n}\\n\",\"keccak256\":\"0xd8122941175d1d5c2983e71717a2fdcc6fe94aa9de08f87eb7c44e3a5f1c2030\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Interface of the ERC-20 standard as defined in the ERC.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the value of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the value of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 value) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\\n * caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 value) external returns (bool);\\n\\n /**\\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\\n * allowance mechanism. `value` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 value) external returns (bool);\\n}\\n\",\"keccak256\":\"0xe06a3f08a987af6ad2e1c1e774405d4fe08f1694b67517438b467cecf0da0ef7\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/IERC20Metadata.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC20} from \\\"../IERC20.sol\\\";\\n\\n/**\\n * @dev Interface for the optional metadata functions from the ERC-20 standard.\\n */\\ninterface IERC20Metadata is IERC20 {\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the symbol of the token.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the decimals places of the token.\\n */\\n function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0x70f2f713b13b7ce4610bcd0ac9fec0f3cc43693b043abcb8dc40a42a726eb330\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Panic.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/Panic.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Helper library for emitting standardized panic codes.\\n *\\n * ```solidity\\n * contract Example {\\n * using Panic for uint256;\\n *\\n * // Use any of the declared internal constants\\n * function foo() { Panic.GENERIC.panic(); }\\n *\\n * // Alternatively\\n * function foo() { Panic.panic(Panic.GENERIC); }\\n * }\\n * ```\\n *\\n * Follows the list from https://github.com/ethereum/solidity/blob/v0.8.24/libsolutil/ErrorCodes.h[libsolutil].\\n *\\n * _Available since v5.1._\\n */\\n// slither-disable-next-line unused-state\\nlibrary Panic {\\n /// @dev generic / unspecified error\\n uint256 internal constant GENERIC = 0x00;\\n /// @dev used by the assert() builtin\\n uint256 internal constant ASSERT = 0x01;\\n /// @dev arithmetic underflow or overflow\\n uint256 internal constant UNDER_OVERFLOW = 0x11;\\n /// @dev division or modulo by zero\\n uint256 internal constant DIVISION_BY_ZERO = 0x12;\\n /// @dev enum conversion error\\n uint256 internal constant ENUM_CONVERSION_ERROR = 0x21;\\n /// @dev invalid encoding in storage\\n uint256 internal constant STORAGE_ENCODING_ERROR = 0x22;\\n /// @dev empty array pop\\n uint256 internal constant EMPTY_ARRAY_POP = 0x31;\\n /// @dev array out of bounds access\\n uint256 internal constant ARRAY_OUT_OF_BOUNDS = 0x32;\\n /// @dev resource error (too large allocation or too large array)\\n uint256 internal constant RESOURCE_ERROR = 0x41;\\n /// @dev calling invalid internal function\\n uint256 internal constant INVALID_INTERNAL_FUNCTION = 0x51;\\n\\n /// @dev Reverts with a panic code. Recommended to use with\\n /// the internal constants with predefined codes.\\n function panic(uint256 code) internal pure {\\n assembly (\\\"memory-safe\\\") {\\n mstore(0x00, 0x4e487b71)\\n mstore(0x20, code)\\n revert(0x1c, 0x24)\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (utils/Strings.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {Math} from \\\"./math/Math.sol\\\";\\nimport {SafeCast} from \\\"./math/SafeCast.sol\\\";\\nimport {SignedMath} from \\\"./math/SignedMath.sol\\\";\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n using SafeCast for *;\\n\\n bytes16 private constant HEX_DIGITS = \\\"0123456789abcdef\\\";\\n uint8 private constant ADDRESS_LENGTH = 20;\\n uint256 private constant SPECIAL_CHARS_LOOKUP =\\n (1 << 0x08) | // backspace\\n (1 << 0x09) | // tab\\n (1 << 0x0a) | // newline\\n (1 << 0x0c) | // form feed\\n (1 << 0x0d) | // carriage return\\n (1 << 0x22) | // double quote\\n (1 << 0x5c); // backslash\\n\\n /**\\n * @dev The `value` string doesn't fit in the specified `length`.\\n */\\n error StringsInsufficientHexLength(uint256 value, uint256 length);\\n\\n /**\\n * @dev The string being parsed contains characters that are not in scope of the given base.\\n */\\n error StringsInvalidChar();\\n\\n /**\\n * @dev The string being parsed is not a properly formatted address.\\n */\\n error StringsInvalidAddressFormat();\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n unchecked {\\n uint256 length = Math.log10(value) + 1;\\n string memory buffer = new string(length);\\n uint256 ptr;\\n assembly (\\\"memory-safe\\\") {\\n ptr := add(buffer, add(32, length))\\n }\\n while (true) {\\n ptr--;\\n assembly (\\\"memory-safe\\\") {\\n mstore8(ptr, byte(mod(value, 10), HEX_DIGITS))\\n }\\n value /= 10;\\n if (value == 0) break;\\n }\\n return buffer;\\n }\\n }\\n\\n /**\\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\\n */\\n function toStringSigned(int256 value) internal pure returns (string memory) {\\n return string.concat(value < 0 ? \\\"-\\\" : \\\"\\\", toString(SignedMath.abs(value)));\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n unchecked {\\n return toHexString(value, Math.log256(value) + 1);\\n }\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n uint256 localValue = value;\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = HEX_DIGITS[localValue & 0xf];\\n localValue >>= 4;\\n }\\n if (localValue != 0) {\\n revert StringsInsufficientHexLength(value, length);\\n }\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal\\n * representation.\\n */\\n function toHexString(address addr) internal pure returns (string memory) {\\n return toHexString(uint256(uint160(addr)), ADDRESS_LENGTH);\\n }\\n\\n /**\\n * @dev Converts an `address` with fixed length of 20 bytes to its checksummed ASCII `string` hexadecimal\\n * representation, according to EIP-55.\\n */\\n function toChecksumHexString(address addr) internal pure returns (string memory) {\\n bytes memory buffer = bytes(toHexString(addr));\\n\\n // hash the hex part of buffer (skip length + 2 bytes, length 40)\\n uint256 hashValue;\\n assembly (\\\"memory-safe\\\") {\\n hashValue := shr(96, keccak256(add(buffer, 0x22), 40))\\n }\\n\\n for (uint256 i = 41; i > 1; --i) {\\n // possible values for buffer[i] are 48 (0) to 57 (9) and 97 (a) to 102 (f)\\n if (hashValue & 0xf > 7 && uint8(buffer[i]) > 96) {\\n // case shift by xoring with 0x20\\n buffer[i] ^= 0x20;\\n }\\n hashValue >>= 4;\\n }\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Returns true if the two strings are equal.\\n */\\n function equal(string memory a, string memory b) internal pure returns (bool) {\\n return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b));\\n }\\n\\n /**\\n * @dev Parse a decimal string and returns the value as a `uint256`.\\n *\\n * Requirements:\\n * - The string must be formatted as `[0-9]*`\\n * - The result must fit into an `uint256` type\\n */\\n function parseUint(string memory input) internal pure returns (uint256) {\\n return parseUint(input, 0, bytes(input).length);\\n }\\n\\n /**\\n * @dev Variant of {parseUint-string} that parses a substring of `input` located between position `begin` (included) and\\n * `end` (excluded).\\n *\\n * Requirements:\\n * - The substring must be formatted as `[0-9]*`\\n * - The result must fit into an `uint256` type\\n */\\n function parseUint(string memory input, uint256 begin, uint256 end) internal pure returns (uint256) {\\n (bool success, uint256 value) = tryParseUint(input, begin, end);\\n if (!success) revert StringsInvalidChar();\\n return value;\\n }\\n\\n /**\\n * @dev Variant of {parseUint-string} that returns false if the parsing fails because of an invalid character.\\n *\\n * NOTE: This function will revert if the result does not fit in a `uint256`.\\n */\\n function tryParseUint(string memory input) internal pure returns (bool success, uint256 value) {\\n return _tryParseUintUncheckedBounds(input, 0, bytes(input).length);\\n }\\n\\n /**\\n * @dev Variant of {parseUint-string-uint256-uint256} that returns false if the parsing fails because of an invalid\\n * character.\\n *\\n * NOTE: This function will revert if the result does not fit in a `uint256`.\\n */\\n function tryParseUint(\\n string memory input,\\n uint256 begin,\\n uint256 end\\n ) internal pure returns (bool success, uint256 value) {\\n if (end > bytes(input).length || begin > end) return (false, 0);\\n return _tryParseUintUncheckedBounds(input, begin, end);\\n }\\n\\n /**\\n * @dev Implementation of {tryParseUint-string-uint256-uint256} that does not check bounds. Caller should make sure that\\n * `begin <= end <= input.length`. Other inputs would result in undefined behavior.\\n */\\n function _tryParseUintUncheckedBounds(\\n string memory input,\\n uint256 begin,\\n uint256 end\\n ) private pure returns (bool success, uint256 value) {\\n bytes memory buffer = bytes(input);\\n\\n uint256 result = 0;\\n for (uint256 i = begin; i < end; ++i) {\\n uint8 chr = _tryParseChr(bytes1(_unsafeReadBytesOffset(buffer, i)));\\n if (chr > 9) return (false, 0);\\n result *= 10;\\n result += chr;\\n }\\n return (true, result);\\n }\\n\\n /**\\n * @dev Parse a decimal string and returns the value as a `int256`.\\n *\\n * Requirements:\\n * - The string must be formatted as `[-+]?[0-9]*`\\n * - The result must fit in an `int256` type.\\n */\\n function parseInt(string memory input) internal pure returns (int256) {\\n return parseInt(input, 0, bytes(input).length);\\n }\\n\\n /**\\n * @dev Variant of {parseInt-string} that parses a substring of `input` located between position `begin` (included) and\\n * `end` (excluded).\\n *\\n * Requirements:\\n * - The substring must be formatted as `[-+]?[0-9]*`\\n * - The result must fit in an `int256` type.\\n */\\n function parseInt(string memory input, uint256 begin, uint256 end) internal pure returns (int256) {\\n (bool success, int256 value) = tryParseInt(input, begin, end);\\n if (!success) revert StringsInvalidChar();\\n return value;\\n }\\n\\n /**\\n * @dev Variant of {parseInt-string} that returns false if the parsing fails because of an invalid character or if\\n * the result does not fit in a `int256`.\\n *\\n * NOTE: This function will revert if the absolute value of the result does not fit in a `uint256`.\\n */\\n function tryParseInt(string memory input) internal pure returns (bool success, int256 value) {\\n return _tryParseIntUncheckedBounds(input, 0, bytes(input).length);\\n }\\n\\n uint256 private constant ABS_MIN_INT256 = 2 ** 255;\\n\\n /**\\n * @dev Variant of {parseInt-string-uint256-uint256} that returns false if the parsing fails because of an invalid\\n * character or if the result does not fit in a `int256`.\\n *\\n * NOTE: This function will revert if the absolute value of the result does not fit in a `uint256`.\\n */\\n function tryParseInt(\\n string memory input,\\n uint256 begin,\\n uint256 end\\n ) internal pure returns (bool success, int256 value) {\\n if (end > bytes(input).length || begin > end) return (false, 0);\\n return _tryParseIntUncheckedBounds(input, begin, end);\\n }\\n\\n /**\\n * @dev Implementation of {tryParseInt-string-uint256-uint256} that does not check bounds. Caller should make sure that\\n * `begin <= end <= input.length`. Other inputs would result in undefined behavior.\\n */\\n function _tryParseIntUncheckedBounds(\\n string memory input,\\n uint256 begin,\\n uint256 end\\n ) private pure returns (bool success, int256 value) {\\n bytes memory buffer = bytes(input);\\n\\n // Check presence of a negative sign.\\n bytes1 sign = begin == end ? bytes1(0) : bytes1(_unsafeReadBytesOffset(buffer, begin)); // don't do out-of-bound (possibly unsafe) read if sub-string is empty\\n bool positiveSign = sign == bytes1(\\\"+\\\");\\n bool negativeSign = sign == bytes1(\\\"-\\\");\\n uint256 offset = (positiveSign || negativeSign).toUint();\\n\\n (bool absSuccess, uint256 absValue) = tryParseUint(input, begin + offset, end);\\n\\n if (absSuccess && absValue < ABS_MIN_INT256) {\\n return (true, negativeSign ? -int256(absValue) : int256(absValue));\\n } else if (absSuccess && negativeSign && absValue == ABS_MIN_INT256) {\\n return (true, type(int256).min);\\n } else return (false, 0);\\n }\\n\\n /**\\n * @dev Parse a hexadecimal string (with or without \\\"0x\\\" prefix), and returns the value as a `uint256`.\\n *\\n * Requirements:\\n * - The string must be formatted as `(0x)?[0-9a-fA-F]*`\\n * - The result must fit in an `uint256` type.\\n */\\n function parseHexUint(string memory input) internal pure returns (uint256) {\\n return parseHexUint(input, 0, bytes(input).length);\\n }\\n\\n /**\\n * @dev Variant of {parseHexUint-string} that parses a substring of `input` located between position `begin` (included) and\\n * `end` (excluded).\\n *\\n * Requirements:\\n * - The substring must be formatted as `(0x)?[0-9a-fA-F]*`\\n * - The result must fit in an `uint256` type.\\n */\\n function parseHexUint(string memory input, uint256 begin, uint256 end) internal pure returns (uint256) {\\n (bool success, uint256 value) = tryParseHexUint(input, begin, end);\\n if (!success) revert StringsInvalidChar();\\n return value;\\n }\\n\\n /**\\n * @dev Variant of {parseHexUint-string} that returns false if the parsing fails because of an invalid character.\\n *\\n * NOTE: This function will revert if the result does not fit in a `uint256`.\\n */\\n function tryParseHexUint(string memory input) internal pure returns (bool success, uint256 value) {\\n return _tryParseHexUintUncheckedBounds(input, 0, bytes(input).length);\\n }\\n\\n /**\\n * @dev Variant of {parseHexUint-string-uint256-uint256} that returns false if the parsing fails because of an\\n * invalid character.\\n *\\n * NOTE: This function will revert if the result does not fit in a `uint256`.\\n */\\n function tryParseHexUint(\\n string memory input,\\n uint256 begin,\\n uint256 end\\n ) internal pure returns (bool success, uint256 value) {\\n if (end > bytes(input).length || begin > end) return (false, 0);\\n return _tryParseHexUintUncheckedBounds(input, begin, end);\\n }\\n\\n /**\\n * @dev Implementation of {tryParseHexUint-string-uint256-uint256} that does not check bounds. Caller should make sure that\\n * `begin <= end <= input.length`. Other inputs would result in undefined behavior.\\n */\\n function _tryParseHexUintUncheckedBounds(\\n string memory input,\\n uint256 begin,\\n uint256 end\\n ) private pure returns (bool success, uint256 value) {\\n bytes memory buffer = bytes(input);\\n\\n // skip 0x prefix if present\\n bool hasPrefix = (end > begin + 1) && bytes2(_unsafeReadBytesOffset(buffer, begin)) == bytes2(\\\"0x\\\"); // don't do out-of-bound (possibly unsafe) read if sub-string is empty\\n uint256 offset = hasPrefix.toUint() * 2;\\n\\n uint256 result = 0;\\n for (uint256 i = begin + offset; i < end; ++i) {\\n uint8 chr = _tryParseChr(bytes1(_unsafeReadBytesOffset(buffer, i)));\\n if (chr > 15) return (false, 0);\\n result *= 16;\\n unchecked {\\n // Multiplying by 16 is equivalent to a shift of 4 bits (with additional overflow check).\\n // This guarantees that adding a value < 16 will not cause an overflow, hence the unchecked.\\n result += chr;\\n }\\n }\\n return (true, result);\\n }\\n\\n /**\\n * @dev Parse a hexadecimal string (with or without \\\"0x\\\" prefix), and returns the value as an `address`.\\n *\\n * Requirements:\\n * - The string must be formatted as `(0x)?[0-9a-fA-F]{40}`\\n */\\n function parseAddress(string memory input) internal pure returns (address) {\\n return parseAddress(input, 0, bytes(input).length);\\n }\\n\\n /**\\n * @dev Variant of {parseAddress-string} that parses a substring of `input` located between position `begin` (included) and\\n * `end` (excluded).\\n *\\n * Requirements:\\n * - The substring must be formatted as `(0x)?[0-9a-fA-F]{40}`\\n */\\n function parseAddress(string memory input, uint256 begin, uint256 end) internal pure returns (address) {\\n (bool success, address value) = tryParseAddress(input, begin, end);\\n if (!success) revert StringsInvalidAddressFormat();\\n return value;\\n }\\n\\n /**\\n * @dev Variant of {parseAddress-string} that returns false if the parsing fails because the input is not a properly\\n * formatted address. See {parseAddress-string} requirements.\\n */\\n function tryParseAddress(string memory input) internal pure returns (bool success, address value) {\\n return tryParseAddress(input, 0, bytes(input).length);\\n }\\n\\n /**\\n * @dev Variant of {parseAddress-string-uint256-uint256} that returns false if the parsing fails because input is not a properly\\n * formatted address. See {parseAddress-string-uint256-uint256} requirements.\\n */\\n function tryParseAddress(\\n string memory input,\\n uint256 begin,\\n uint256 end\\n ) internal pure returns (bool success, address value) {\\n if (end > bytes(input).length || begin > end) return (false, address(0));\\n\\n bool hasPrefix = (end > begin + 1) && bytes2(_unsafeReadBytesOffset(bytes(input), begin)) == bytes2(\\\"0x\\\"); // don't do out-of-bound (possibly unsafe) read if sub-string is empty\\n uint256 expectedLength = 40 + hasPrefix.toUint() * 2;\\n\\n // check that input is the correct length\\n if (end - begin == expectedLength) {\\n // length guarantees that this does not overflow, and value is at most type(uint160).max\\n (bool s, uint256 v) = _tryParseHexUintUncheckedBounds(input, begin, end);\\n return (s, address(uint160(v)));\\n } else {\\n return (false, address(0));\\n }\\n }\\n\\n function _tryParseChr(bytes1 chr) private pure returns (uint8) {\\n uint8 value = uint8(chr);\\n\\n // Try to parse `chr`:\\n // - Case 1: [0-9]\\n // - Case 2: [a-f]\\n // - Case 3: [A-F]\\n // - otherwise not supported\\n unchecked {\\n if (value > 47 && value < 58) value -= 48;\\n else if (value > 96 && value < 103) value -= 87;\\n else if (value > 64 && value < 71) value -= 55;\\n else return type(uint8).max;\\n }\\n\\n return value;\\n }\\n\\n /**\\n * @dev Escape special characters in JSON strings. This can be useful to prevent JSON injection in NFT metadata.\\n *\\n * WARNING: This function should only be used in double quoted JSON strings. Single quotes are not escaped.\\n *\\n * NOTE: This function escapes all unicode characters, and not just the ones in ranges defined in section 2.5 of\\n * RFC-4627 (U+0000 to U+001F, U+0022 and U+005C). ECMAScript's `JSON.parse` does recover escaped unicode\\n * characters that are not in this range, but other tooling may provide different results.\\n */\\n function escapeJSON(string memory input) internal pure returns (string memory) {\\n bytes memory buffer = bytes(input);\\n bytes memory output = new bytes(2 * buffer.length); // worst case scenario\\n uint256 outputLength = 0;\\n\\n for (uint256 i; i < buffer.length; ++i) {\\n bytes1 char = bytes1(_unsafeReadBytesOffset(buffer, i));\\n if (((SPECIAL_CHARS_LOOKUP & (1 << uint8(char))) != 0)) {\\n output[outputLength++] = \\\"\\\\\\\\\\\";\\n if (char == 0x08) output[outputLength++] = \\\"b\\\";\\n else if (char == 0x09) output[outputLength++] = \\\"t\\\";\\n else if (char == 0x0a) output[outputLength++] = \\\"n\\\";\\n else if (char == 0x0c) output[outputLength++] = \\\"f\\\";\\n else if (char == 0x0d) output[outputLength++] = \\\"r\\\";\\n else if (char == 0x5c) output[outputLength++] = \\\"\\\\\\\\\\\";\\n else if (char == 0x22) {\\n // solhint-disable-next-line quotes\\n output[outputLength++] = '\\\"';\\n }\\n } else {\\n output[outputLength++] = char;\\n }\\n }\\n // write the actual length and deallocate unused memory\\n assembly (\\\"memory-safe\\\") {\\n mstore(output, outputLength)\\n mstore(0x40, add(output, shl(5, shr(5, add(outputLength, 63)))))\\n }\\n\\n return string(output);\\n }\\n\\n /**\\n * @dev Reads a bytes32 from a bytes array without bounds checking.\\n *\\n * NOTE: making this function internal would mean it could be used with memory unsafe offset, and marking the\\n * assembly block as such would prevent some optimizations.\\n */\\n function _unsafeReadBytesOffset(bytes memory buffer, uint256 offset) private pure returns (bytes32 value) {\\n // This is not memory safe in the general case, but all calls to this private function are within bounds.\\n assembly (\\\"memory-safe\\\") {\\n value := mload(add(buffer, add(0x20, offset)))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x81c274a60a7ae232ae3dc9ff3a4011b4849a853c13b0832cd3351bb1bb2f0dae\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {Panic} from \\\"../Panic.sol\\\";\\nimport {SafeCast} from \\\"./SafeCast.sol\\\";\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n enum Rounding {\\n Floor, // Toward negative infinity\\n Ceil, // Toward positive infinity\\n Trunc, // Toward zero\\n Expand // Away from zero\\n }\\n\\n /**\\n * @dev Return the 512-bit addition of two uint256.\\n *\\n * The result is stored in two 256 variables such that sum = high * 2\\u00b2\\u2075\\u2076 + low.\\n */\\n function add512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {\\n assembly (\\\"memory-safe\\\") {\\n low := add(a, b)\\n high := lt(low, a)\\n }\\n }\\n\\n /**\\n * @dev Return the 512-bit multiplication of two uint256.\\n *\\n * The result is stored in two 256 variables such that product = high * 2\\u00b2\\u2075\\u2076 + low.\\n */\\n function mul512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {\\n // 512-bit multiply [high low] = x * y. Compute the product mod 2\\u00b2\\u2075\\u2076 and mod 2\\u00b2\\u2075\\u2076 - 1, then use\\n // the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = high * 2\\u00b2\\u2075\\u2076 + low.\\n assembly (\\\"memory-safe\\\") {\\n let mm := mulmod(a, b, not(0))\\n low := mul(a, b)\\n high := sub(sub(mm, low), lt(mm, low))\\n }\\n }\\n\\n /**\\n * @dev Returns the addition of two unsigned integers, with a success flag (no overflow).\\n */\\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\\n unchecked {\\n uint256 c = a + b;\\n success = c >= a;\\n result = c * SafeCast.toUint(success);\\n }\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, with a success flag (no overflow).\\n */\\n function trySub(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\\n unchecked {\\n uint256 c = a - b;\\n success = c <= a;\\n result = c * SafeCast.toUint(success);\\n }\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, with a success flag (no overflow).\\n */\\n function tryMul(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\\n unchecked {\\n uint256 c = a * b;\\n assembly (\\\"memory-safe\\\") {\\n // Only true when the multiplication doesn't overflow\\n // (c / a == b) || (a == 0)\\n success := or(eq(div(c, a), b), iszero(a))\\n }\\n // equivalent to: success ? c : 0\\n result = c * SafeCast.toUint(success);\\n }\\n }\\n\\n /**\\n * @dev Returns the division of two unsigned integers, with a success flag (no division by zero).\\n */\\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\\n unchecked {\\n success = b > 0;\\n assembly (\\\"memory-safe\\\") {\\n // The `DIV` opcode returns zero when the denominator is 0.\\n result := div(a, b)\\n }\\n }\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers, with a success flag (no division by zero).\\n */\\n function tryMod(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\\n unchecked {\\n success = b > 0;\\n assembly (\\\"memory-safe\\\") {\\n // The `MOD` opcode returns zero when the denominator is 0.\\n result := mod(a, b)\\n }\\n }\\n }\\n\\n /**\\n * @dev Unsigned saturating addition, bounds to `2\\u00b2\\u2075\\u2076 - 1` instead of overflowing.\\n */\\n function saturatingAdd(uint256 a, uint256 b) internal pure returns (uint256) {\\n (bool success, uint256 result) = tryAdd(a, b);\\n return ternary(success, result, type(uint256).max);\\n }\\n\\n /**\\n * @dev Unsigned saturating subtraction, bounds to zero instead of overflowing.\\n */\\n function saturatingSub(uint256 a, uint256 b) internal pure returns (uint256) {\\n (, uint256 result) = trySub(a, b);\\n return result;\\n }\\n\\n /**\\n * @dev Unsigned saturating multiplication, bounds to `2\\u00b2\\u2075\\u2076 - 1` instead of overflowing.\\n */\\n function saturatingMul(uint256 a, uint256 b) internal pure returns (uint256) {\\n (bool success, uint256 result) = tryMul(a, b);\\n return ternary(success, result, type(uint256).max);\\n }\\n\\n /**\\n * @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant.\\n *\\n * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone.\\n * However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute\\n * one branch when needed, making this function more expensive.\\n */\\n function ternary(bool condition, uint256 a, uint256 b) internal pure returns (uint256) {\\n unchecked {\\n // branchless ternary works because:\\n // b ^ (a ^ b) == a\\n // b ^ 0 == b\\n return b ^ ((a ^ b) * SafeCast.toUint(condition));\\n }\\n }\\n\\n /**\\n * @dev Returns the largest of two numbers.\\n */\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return ternary(a > b, a, b);\\n }\\n\\n /**\\n * @dev Returns the smallest of two numbers.\\n */\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return ternary(a < b, a, b);\\n }\\n\\n /**\\n * @dev Returns the average of two numbers. The result is rounded towards\\n * zero.\\n */\\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b) / 2 can overflow.\\n return (a & b) + (a ^ b) / 2;\\n }\\n\\n /**\\n * @dev Returns the ceiling of the division of two numbers.\\n *\\n * This differs from standard division with `/` in that it rounds towards infinity instead\\n * of rounding towards zero.\\n */\\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n if (b == 0) {\\n // Guarantee the same behavior as in a regular Solidity division.\\n Panic.panic(Panic.DIVISION_BY_ZERO);\\n }\\n\\n // The following calculation ensures accurate ceiling division without overflow.\\n // Since a is non-zero, (a - 1) / b will not overflow.\\n // The largest possible result occurs when (a - 1) / b is type(uint256).max,\\n // but the largest value we can obtain is type(uint256).max - 1, which happens\\n // when a = type(uint256).max and b = 1.\\n unchecked {\\n return SafeCast.toUint(a > 0) * ((a - 1) / b + 1);\\n }\\n }\\n\\n /**\\n * @dev Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or\\n * denominator == 0.\\n *\\n * Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by\\n * Uniswap Labs also under MIT license.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\\n unchecked {\\n (uint256 high, uint256 low) = mul512(x, y);\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (high == 0) {\\n // Solidity will revert if denominator == 0, unlike the div opcode on its own.\\n // The surrounding unchecked block does not change this fact.\\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\\n return low / denominator;\\n }\\n\\n // Make sure the result is less than 2\\u00b2\\u2075\\u2076. Also prevents denominator == 0.\\n if (denominator <= high) {\\n Panic.panic(ternary(denominator == 0, Panic.DIVISION_BY_ZERO, Panic.UNDER_OVERFLOW));\\n }\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [high low].\\n uint256 remainder;\\n assembly (\\\"memory-safe\\\") {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n high := sub(high, gt(remainder, low))\\n low := sub(low, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator.\\n // Always >= 1. See https://cs.stackexchange.com/q/138556/92363.\\n\\n uint256 twos = denominator & (0 - denominator);\\n assembly (\\\"memory-safe\\\") {\\n // Divide denominator by twos.\\n denominator := div(denominator, twos)\\n\\n // Divide [high low] by twos.\\n low := div(low, twos)\\n\\n // Flip twos such that it is 2\\u00b2\\u2075\\u2076 / twos. If twos is zero, then it becomes one.\\n twos := add(div(sub(0, twos), twos), 1)\\n }\\n\\n // Shift in bits from high into low.\\n low |= high * twos;\\n\\n // Invert denominator mod 2\\u00b2\\u2075\\u2076. Now that denominator is an odd number, it has an inverse modulo 2\\u00b2\\u2075\\u2076 such\\n // that denominator * inv \\u2261 1 mod 2\\u00b2\\u2075\\u2076. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv \\u2261 1 mod 2\\u2074.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also\\n // works in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u2078\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u00b9\\u2076\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u00b3\\u00b2\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u2076\\u2074\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u00b9\\u00b2\\u2078\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u00b2\\u2075\\u2076\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2\\u00b2\\u2075\\u2076. Since the preconditions guarantee that the outcome is\\n // less than 2\\u00b2\\u2075\\u2076, this is the final result. We don't need to compute the high bits of the result and high\\n // is no longer required.\\n result = low * inverse;\\n return result;\\n }\\n }\\n\\n /**\\n * @dev Calculates x * y / denominator with full precision, following the selected rounding direction.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\\n return mulDiv(x, y, denominator) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0);\\n }\\n\\n /**\\n * @dev Calculates floor(x * y >> n) with full precision. Throws if result overflows a uint256.\\n */\\n function mulShr(uint256 x, uint256 y, uint8 n) internal pure returns (uint256 result) {\\n unchecked {\\n (uint256 high, uint256 low) = mul512(x, y);\\n if (high >= 1 << n) {\\n Panic.panic(Panic.UNDER_OVERFLOW);\\n }\\n return (high << (256 - n)) | (low >> n);\\n }\\n }\\n\\n /**\\n * @dev Calculates x * y >> n with full precision, following the selected rounding direction.\\n */\\n function mulShr(uint256 x, uint256 y, uint8 n, Rounding rounding) internal pure returns (uint256) {\\n return mulShr(x, y, n) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, 1 << n) > 0);\\n }\\n\\n /**\\n * @dev Calculate the modular multiplicative inverse of a number in Z/nZ.\\n *\\n * If n is a prime, then Z/nZ is a field. In that case all elements are inversible, except 0.\\n * If n is not a prime, then Z/nZ is not a field, and some elements might not be inversible.\\n *\\n * If the input value is not inversible, 0 is returned.\\n *\\n * NOTE: If you know for sure that n is (big) a prime, it may be cheaper to use Fermat's little theorem and get the\\n * inverse using `Math.modExp(a, n - 2, n)`. See {invModPrime}.\\n */\\n function invMod(uint256 a, uint256 n) internal pure returns (uint256) {\\n unchecked {\\n if (n == 0) return 0;\\n\\n // The inverse modulo is calculated using the Extended Euclidean Algorithm (iterative version)\\n // Used to compute integers x and y such that: ax + ny = gcd(a, n).\\n // When the gcd is 1, then the inverse of a modulo n exists and it's x.\\n // ax + ny = 1\\n // ax = 1 + (-y)n\\n // ax \\u2261 1 (mod n) # x is the inverse of a modulo n\\n\\n // If the remainder is 0 the gcd is n right away.\\n uint256 remainder = a % n;\\n uint256 gcd = n;\\n\\n // Therefore the initial coefficients are:\\n // ax + ny = gcd(a, n) = n\\n // 0a + 1n = n\\n int256 x = 0;\\n int256 y = 1;\\n\\n while (remainder != 0) {\\n uint256 quotient = gcd / remainder;\\n\\n (gcd, remainder) = (\\n // The old remainder is the next gcd to try.\\n remainder,\\n // Compute the next remainder.\\n // Can't overflow given that (a % gcd) * (gcd // (a % gcd)) <= gcd\\n // where gcd is at most n (capped to type(uint256).max)\\n gcd - remainder * quotient\\n );\\n\\n (x, y) = (\\n // Increment the coefficient of a.\\n y,\\n // Decrement the coefficient of n.\\n // Can overflow, but the result is casted to uint256 so that the\\n // next value of y is \\\"wrapped around\\\" to a value between 0 and n - 1.\\n x - y * int256(quotient)\\n );\\n }\\n\\n if (gcd != 1) return 0; // No inverse exists.\\n return ternary(x < 0, n - uint256(-x), uint256(x)); // Wrap the result if it's negative.\\n }\\n }\\n\\n /**\\n * @dev Variant of {invMod}. More efficient, but only works if `p` is known to be a prime greater than `2`.\\n *\\n * From https://en.wikipedia.org/wiki/Fermat%27s_little_theorem[Fermat's little theorem], we know that if p is\\n * prime, then `a**(p-1) \\u2261 1 mod p`. As a consequence, we have `a * a**(p-2) \\u2261 1 mod p`, which means that\\n * `a**(p-2)` is the modular multiplicative inverse of a in Fp.\\n *\\n * NOTE: this function does NOT check that `p` is a prime greater than `2`.\\n */\\n function invModPrime(uint256 a, uint256 p) internal view returns (uint256) {\\n unchecked {\\n return Math.modExp(a, p - 2, p);\\n }\\n }\\n\\n /**\\n * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m)\\n *\\n * Requirements:\\n * - modulus can't be zero\\n * - underlying staticcall to precompile must succeed\\n *\\n * IMPORTANT: The result is only valid if the underlying call succeeds. When using this function, make\\n * sure the chain you're using it on supports the precompiled contract for modular exponentiation\\n * at address 0x05 as specified in https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise,\\n * the underlying function will succeed given the lack of a revert, but the result may be incorrectly\\n * interpreted as 0.\\n */\\n function modExp(uint256 b, uint256 e, uint256 m) internal view returns (uint256) {\\n (bool success, uint256 result) = tryModExp(b, e, m);\\n if (!success) {\\n Panic.panic(Panic.DIVISION_BY_ZERO);\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m).\\n * It includes a success flag indicating if the operation succeeded. Operation will be marked as failed if trying\\n * to operate modulo 0 or if the underlying precompile reverted.\\n *\\n * IMPORTANT: The result is only valid if the success flag is true. When using this function, make sure the chain\\n * you're using it on supports the precompiled contract for modular exponentiation at address 0x05 as specified in\\n * https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise, the underlying function will succeed given the lack\\n * of a revert, but the result may be incorrectly interpreted as 0.\\n */\\n function tryModExp(uint256 b, uint256 e, uint256 m) internal view returns (bool success, uint256 result) {\\n if (m == 0) return (false, 0);\\n assembly (\\\"memory-safe\\\") {\\n let ptr := mload(0x40)\\n // | Offset | Content | Content (Hex) |\\n // |-----------|------------|--------------------------------------------------------------------|\\n // | 0x00:0x1f | size of b | 0x0000000000000000000000000000000000000000000000000000000000000020 |\\n // | 0x20:0x3f | size of e | 0x0000000000000000000000000000000000000000000000000000000000000020 |\\n // | 0x40:0x5f | size of m | 0x0000000000000000000000000000000000000000000000000000000000000020 |\\n // | 0x60:0x7f | value of b | 0x<.............................................................b> |\\n // | 0x80:0x9f | value of e | 0x<.............................................................e> |\\n // | 0xa0:0xbf | value of m | 0x<.............................................................m> |\\n mstore(ptr, 0x20)\\n mstore(add(ptr, 0x20), 0x20)\\n mstore(add(ptr, 0x40), 0x20)\\n mstore(add(ptr, 0x60), b)\\n mstore(add(ptr, 0x80), e)\\n mstore(add(ptr, 0xa0), m)\\n\\n // Given the result < m, it's guaranteed to fit in 32 bytes,\\n // so we can use the memory scratch space located at offset 0.\\n success := staticcall(gas(), 0x05, ptr, 0xc0, 0x00, 0x20)\\n result := mload(0x00)\\n }\\n }\\n\\n /**\\n * @dev Variant of {modExp} that supports inputs of arbitrary length.\\n */\\n function modExp(bytes memory b, bytes memory e, bytes memory m) internal view returns (bytes memory) {\\n (bool success, bytes memory result) = tryModExp(b, e, m);\\n if (!success) {\\n Panic.panic(Panic.DIVISION_BY_ZERO);\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Variant of {tryModExp} that supports inputs of arbitrary length.\\n */\\n function tryModExp(\\n bytes memory b,\\n bytes memory e,\\n bytes memory m\\n ) internal view returns (bool success, bytes memory result) {\\n if (_zeroBytes(m)) return (false, new bytes(0));\\n\\n uint256 mLen = m.length;\\n\\n // Encode call args in result and move the free memory pointer\\n result = abi.encodePacked(b.length, e.length, mLen, b, e, m);\\n\\n assembly (\\\"memory-safe\\\") {\\n let dataPtr := add(result, 0x20)\\n // Write result on top of args to avoid allocating extra memory.\\n success := staticcall(gas(), 0x05, dataPtr, mload(result), dataPtr, mLen)\\n // Overwrite the length.\\n // result.length > returndatasize() is guaranteed because returndatasize() == m.length\\n mstore(result, mLen)\\n // Set the memory pointer after the returned data.\\n mstore(0x40, add(dataPtr, mLen))\\n }\\n }\\n\\n /**\\n * @dev Returns whether the provided byte array is zero.\\n */\\n function _zeroBytes(bytes memory byteArray) private pure returns (bool) {\\n for (uint256 i = 0; i < byteArray.length; ++i) {\\n if (byteArray[i] != 0) {\\n return false;\\n }\\n }\\n return true;\\n }\\n\\n /**\\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded\\n * towards zero.\\n *\\n * This method is based on Newton's method for computing square roots; the algorithm is restricted to only\\n * using integer operations.\\n */\\n function sqrt(uint256 a) internal pure returns (uint256) {\\n unchecked {\\n // Take care of easy edge cases when a == 0 or a == 1\\n if (a <= 1) {\\n return a;\\n }\\n\\n // In this function, we use Newton's method to get a root of `f(x) := x\\u00b2 - a`. It involves building a\\n // sequence x_n that converges toward sqrt(a). For each iteration x_n, we also define the error between\\n // the current value as `\\u03b5_n = | x_n - sqrt(a) |`.\\n //\\n // For our first estimation, we consider `e` the smallest power of 2 which is bigger than the square root\\n // of the target. (i.e. `2**(e-1) \\u2264 sqrt(a) < 2**e`). We know that `e \\u2264 128` because `(2\\u00b9\\u00b2\\u2078)\\u00b2 = 2\\u00b2\\u2075\\u2076` is\\n // bigger than any uint256.\\n //\\n // By noticing that\\n // `2**(e-1) \\u2264 sqrt(a) < 2**e \\u2192 (2**(e-1))\\u00b2 \\u2264 a < (2**e)\\u00b2 \\u2192 2**(2*e-2) \\u2264 a < 2**(2*e)`\\n // we can deduce that `e - 1` is `log2(a) / 2`. We can thus compute `x_n = 2**(e-1)` using a method similar\\n // to the msb function.\\n uint256 aa = a;\\n uint256 xn = 1;\\n\\n if (aa >= (1 << 128)) {\\n aa >>= 128;\\n xn <<= 64;\\n }\\n if (aa >= (1 << 64)) {\\n aa >>= 64;\\n xn <<= 32;\\n }\\n if (aa >= (1 << 32)) {\\n aa >>= 32;\\n xn <<= 16;\\n }\\n if (aa >= (1 << 16)) {\\n aa >>= 16;\\n xn <<= 8;\\n }\\n if (aa >= (1 << 8)) {\\n aa >>= 8;\\n xn <<= 4;\\n }\\n if (aa >= (1 << 4)) {\\n aa >>= 4;\\n xn <<= 2;\\n }\\n if (aa >= (1 << 2)) {\\n xn <<= 1;\\n }\\n\\n // We now have x_n such that `x_n = 2**(e-1) \\u2264 sqrt(a) < 2**e = 2 * x_n`. This implies \\u03b5_n \\u2264 2**(e-1).\\n //\\n // We can refine our estimation by noticing that the middle of that interval minimizes the error.\\n // If we move x_n to equal 2**(e-1) + 2**(e-2), then we reduce the error to \\u03b5_n \\u2264 2**(e-2).\\n // This is going to be our x_0 (and \\u03b5_0)\\n xn = (3 * xn) >> 1; // \\u03b5_0 := | x_0 - sqrt(a) | \\u2264 2**(e-2)\\n\\n // From here, Newton's method give us:\\n // x_{n+1} = (x_n + a / x_n) / 2\\n //\\n // One should note that:\\n // x_{n+1}\\u00b2 - a = ((x_n + a / x_n) / 2)\\u00b2 - a\\n // = ((x_n\\u00b2 + a) / (2 * x_n))\\u00b2 - a\\n // = (x_n\\u2074 + 2 * a * x_n\\u00b2 + a\\u00b2) / (4 * x_n\\u00b2) - a\\n // = (x_n\\u2074 + 2 * a * x_n\\u00b2 + a\\u00b2 - 4 * a * x_n\\u00b2) / (4 * x_n\\u00b2)\\n // = (x_n\\u2074 - 2 * a * x_n\\u00b2 + a\\u00b2) / (4 * x_n\\u00b2)\\n // = (x_n\\u00b2 - a)\\u00b2 / (2 * x_n)\\u00b2\\n // = ((x_n\\u00b2 - a) / (2 * x_n))\\u00b2\\n // \\u2265 0\\n // Which proves that for all n \\u2265 1, sqrt(a) \\u2264 x_n\\n //\\n // This gives us the proof of quadratic convergence of the sequence:\\n // \\u03b5_{n+1} = | x_{n+1} - sqrt(a) |\\n // = | (x_n + a / x_n) / 2 - sqrt(a) |\\n // = | (x_n\\u00b2 + a - 2*x_n*sqrt(a)) / (2 * x_n) |\\n // = | (x_n - sqrt(a))\\u00b2 / (2 * x_n) |\\n // = | \\u03b5_n\\u00b2 / (2 * x_n) |\\n // = \\u03b5_n\\u00b2 / | (2 * x_n) |\\n //\\n // For the first iteration, we have a special case where x_0 is known:\\n // \\u03b5_1 = \\u03b5_0\\u00b2 / | (2 * x_0) |\\n // \\u2264 (2**(e-2))\\u00b2 / (2 * (2**(e-1) + 2**(e-2)))\\n // \\u2264 2**(2*e-4) / (3 * 2**(e-1))\\n // \\u2264 2**(e-3) / 3\\n // \\u2264 2**(e-3-log2(3))\\n // \\u2264 2**(e-4.5)\\n //\\n // For the following iterations, we use the fact that, 2**(e-1) \\u2264 sqrt(a) \\u2264 x_n:\\n // \\u03b5_{n+1} = \\u03b5_n\\u00b2 / | (2 * x_n) |\\n // \\u2264 (2**(e-k))\\u00b2 / (2 * 2**(e-1))\\n // \\u2264 2**(2*e-2*k) / 2**e\\n // \\u2264 2**(e-2*k)\\n xn = (xn + a / xn) >> 1; // \\u03b5_1 := | x_1 - sqrt(a) | \\u2264 2**(e-4.5) -- special case, see above\\n xn = (xn + a / xn) >> 1; // \\u03b5_2 := | x_2 - sqrt(a) | \\u2264 2**(e-9) -- general case with k = 4.5\\n xn = (xn + a / xn) >> 1; // \\u03b5_3 := | x_3 - sqrt(a) | \\u2264 2**(e-18) -- general case with k = 9\\n xn = (xn + a / xn) >> 1; // \\u03b5_4 := | x_4 - sqrt(a) | \\u2264 2**(e-36) -- general case with k = 18\\n xn = (xn + a / xn) >> 1; // \\u03b5_5 := | x_5 - sqrt(a) | \\u2264 2**(e-72) -- general case with k = 36\\n xn = (xn + a / xn) >> 1; // \\u03b5_6 := | x_6 - sqrt(a) | \\u2264 2**(e-144) -- general case with k = 72\\n\\n // Because e \\u2264 128 (as discussed during the first estimation phase), we know have reached a precision\\n // \\u03b5_6 \\u2264 2**(e-144) < 1. Given we're operating on integers, then we can ensure that xn is now either\\n // sqrt(a) or sqrt(a) + 1.\\n return xn - SafeCast.toUint(xn > a / xn);\\n }\\n }\\n\\n /**\\n * @dev Calculates sqrt(a), following the selected rounding direction.\\n */\\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = sqrt(a);\\n return result + SafeCast.toUint(unsignedRoundsUp(rounding) && result * result < a);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 2 of a positive value rounded towards zero.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 x) internal pure returns (uint256 r) {\\n // If value has upper 128 bits set, log2 result is at least 128\\n r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;\\n // If upper 64 bits of 128-bit half set, add 64 to result\\n r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;\\n // If upper 32 bits of 64-bit half set, add 32 to result\\n r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;\\n // If upper 16 bits of 32-bit half set, add 16 to result\\n r |= SafeCast.toUint((x >> r) > 0xffff) << 4;\\n // If upper 8 bits of 16-bit half set, add 8 to result\\n r |= SafeCast.toUint((x >> r) > 0xff) << 3;\\n // If upper 4 bits of 8-bit half set, add 4 to result\\n r |= SafeCast.toUint((x >> r) > 0xf) << 2;\\n\\n // Shifts value right by the current result and use it as an index into this lookup table:\\n //\\n // | x (4 bits) | index | table[index] = MSB position |\\n // |------------|---------|-----------------------------|\\n // | 0000 | 0 | table[0] = 0 |\\n // | 0001 | 1 | table[1] = 0 |\\n // | 0010 | 2 | table[2] = 1 |\\n // | 0011 | 3 | table[3] = 1 |\\n // | 0100 | 4 | table[4] = 2 |\\n // | 0101 | 5 | table[5] = 2 |\\n // | 0110 | 6 | table[6] = 2 |\\n // | 0111 | 7 | table[7] = 2 |\\n // | 1000 | 8 | table[8] = 3 |\\n // | 1001 | 9 | table[9] = 3 |\\n // | 1010 | 10 | table[10] = 3 |\\n // | 1011 | 11 | table[11] = 3 |\\n // | 1100 | 12 | table[12] = 3 |\\n // | 1101 | 13 | table[13] = 3 |\\n // | 1110 | 14 | table[14] = 3 |\\n // | 1111 | 15 | table[15] = 3 |\\n //\\n // The lookup table is represented as a 32-byte value with the MSB positions for 0-15 in the last 16 bytes.\\n assembly (\\\"memory-safe\\\") {\\n r := or(r, byte(shr(r, x), 0x0000010102020202030303030303030300000000000000000000000000000000))\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log2(value);\\n return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << result < value);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 10 of a positive value rounded towards zero.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >= 10 ** 64) {\\n value /= 10 ** 64;\\n result += 64;\\n }\\n if (value >= 10 ** 32) {\\n value /= 10 ** 32;\\n result += 32;\\n }\\n if (value >= 10 ** 16) {\\n value /= 10 ** 16;\\n result += 16;\\n }\\n if (value >= 10 ** 8) {\\n value /= 10 ** 8;\\n result += 8;\\n }\\n if (value >= 10 ** 4) {\\n value /= 10 ** 4;\\n result += 4;\\n }\\n if (value >= 10 ** 2) {\\n value /= 10 ** 2;\\n result += 2;\\n }\\n if (value >= 10 ** 1) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log10(value);\\n return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 10 ** result < value);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 256 of a positive value rounded towards zero.\\n * Returns 0 if given 0.\\n *\\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\\n */\\n function log256(uint256 x) internal pure returns (uint256 r) {\\n // If value has upper 128 bits set, log2 result is at least 128\\n r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;\\n // If upper 64 bits of 128-bit half set, add 64 to result\\n r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;\\n // If upper 32 bits of 64-bit half set, add 32 to result\\n r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;\\n // If upper 16 bits of 32-bit half set, add 16 to result\\n r |= SafeCast.toUint((x >> r) > 0xffff) << 4;\\n // Add 1 if upper 8 bits of 16-bit half set, and divide accumulated result by 8\\n return (r >> 3) | SafeCast.toUint((x >> r) > 0xff);\\n }\\n\\n /**\\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log256(value);\\n return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << (result << 3) < value);\\n }\\n }\\n\\n /**\\n * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.\\n */\\n function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {\\n return uint8(rounding) % 2 == 1;\\n }\\n}\\n\",\"keccak256\":\"0x1225214420c83ebcca88f2ae2b50f053aaa7df7bd684c3e878d334627f2edfc6\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/SafeCast.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SafeCast.sol)\\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Wrappers over Solidity's uintXX/intXX/bool casting operators with added overflow\\n * checks.\\n *\\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\\n * easily result in undesired exploitation or bugs, since developers usually\\n * assume that overflows raise errors. `SafeCast` restores this intuition by\\n * reverting the transaction when such an operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeCast {\\n /**\\n * @dev Value doesn't fit in an uint of `bits` size.\\n */\\n error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value);\\n\\n /**\\n * @dev An int value doesn't fit in an uint of `bits` size.\\n */\\n error SafeCastOverflowedIntToUint(int256 value);\\n\\n /**\\n * @dev Value doesn't fit in an int of `bits` size.\\n */\\n error SafeCastOverflowedIntDowncast(uint8 bits, int256 value);\\n\\n /**\\n * @dev An uint value doesn't fit in an int of `bits` size.\\n */\\n error SafeCastOverflowedUintToInt(uint256 value);\\n\\n /**\\n * @dev Returns the downcasted uint248 from uint256, reverting on\\n * overflow (when the input is greater than largest uint248).\\n *\\n * Counterpart to Solidity's `uint248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n */\\n function toUint248(uint256 value) internal pure returns (uint248) {\\n if (value > type(uint248).max) {\\n revert SafeCastOverflowedUintDowncast(248, value);\\n }\\n return uint248(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint240 from uint256, reverting on\\n * overflow (when the input is greater than largest uint240).\\n *\\n * Counterpart to Solidity's `uint240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n */\\n function toUint240(uint256 value) internal pure returns (uint240) {\\n if (value > type(uint240).max) {\\n revert SafeCastOverflowedUintDowncast(240, value);\\n }\\n return uint240(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint232 from uint256, reverting on\\n * overflow (when the input is greater than largest uint232).\\n *\\n * Counterpart to Solidity's `uint232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n */\\n function toUint232(uint256 value) internal pure returns (uint232) {\\n if (value > type(uint232).max) {\\n revert SafeCastOverflowedUintDowncast(232, value);\\n }\\n return uint232(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint224 from uint256, reverting on\\n * overflow (when the input is greater than largest uint224).\\n *\\n * Counterpart to Solidity's `uint224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n */\\n function toUint224(uint256 value) internal pure returns (uint224) {\\n if (value > type(uint224).max) {\\n revert SafeCastOverflowedUintDowncast(224, value);\\n }\\n return uint224(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint216 from uint256, reverting on\\n * overflow (when the input is greater than largest uint216).\\n *\\n * Counterpart to Solidity's `uint216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n */\\n function toUint216(uint256 value) internal pure returns (uint216) {\\n if (value > type(uint216).max) {\\n revert SafeCastOverflowedUintDowncast(216, value);\\n }\\n return uint216(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint208 from uint256, reverting on\\n * overflow (when the input is greater than largest uint208).\\n *\\n * Counterpart to Solidity's `uint208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n */\\n function toUint208(uint256 value) internal pure returns (uint208) {\\n if (value > type(uint208).max) {\\n revert SafeCastOverflowedUintDowncast(208, value);\\n }\\n return uint208(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint200 from uint256, reverting on\\n * overflow (when the input is greater than largest uint200).\\n *\\n * Counterpart to Solidity's `uint200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n */\\n function toUint200(uint256 value) internal pure returns (uint200) {\\n if (value > type(uint200).max) {\\n revert SafeCastOverflowedUintDowncast(200, value);\\n }\\n return uint200(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint192 from uint256, reverting on\\n * overflow (when the input is greater than largest uint192).\\n *\\n * Counterpart to Solidity's `uint192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n */\\n function toUint192(uint256 value) internal pure returns (uint192) {\\n if (value > type(uint192).max) {\\n revert SafeCastOverflowedUintDowncast(192, value);\\n }\\n return uint192(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint184 from uint256, reverting on\\n * overflow (when the input is greater than largest uint184).\\n *\\n * Counterpart to Solidity's `uint184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n */\\n function toUint184(uint256 value) internal pure returns (uint184) {\\n if (value > type(uint184).max) {\\n revert SafeCastOverflowedUintDowncast(184, value);\\n }\\n return uint184(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint176 from uint256, reverting on\\n * overflow (when the input is greater than largest uint176).\\n *\\n * Counterpart to Solidity's `uint176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n */\\n function toUint176(uint256 value) internal pure returns (uint176) {\\n if (value > type(uint176).max) {\\n revert SafeCastOverflowedUintDowncast(176, value);\\n }\\n return uint176(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint168 from uint256, reverting on\\n * overflow (when the input is greater than largest uint168).\\n *\\n * Counterpart to Solidity's `uint168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n */\\n function toUint168(uint256 value) internal pure returns (uint168) {\\n if (value > type(uint168).max) {\\n revert SafeCastOverflowedUintDowncast(168, value);\\n }\\n return uint168(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint160 from uint256, reverting on\\n * overflow (when the input is greater than largest uint160).\\n *\\n * Counterpart to Solidity's `uint160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n */\\n function toUint160(uint256 value) internal pure returns (uint160) {\\n if (value > type(uint160).max) {\\n revert SafeCastOverflowedUintDowncast(160, value);\\n }\\n return uint160(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint152 from uint256, reverting on\\n * overflow (when the input is greater than largest uint152).\\n *\\n * Counterpart to Solidity's `uint152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n */\\n function toUint152(uint256 value) internal pure returns (uint152) {\\n if (value > type(uint152).max) {\\n revert SafeCastOverflowedUintDowncast(152, value);\\n }\\n return uint152(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint144 from uint256, reverting on\\n * overflow (when the input is greater than largest uint144).\\n *\\n * Counterpart to Solidity's `uint144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n */\\n function toUint144(uint256 value) internal pure returns (uint144) {\\n if (value > type(uint144).max) {\\n revert SafeCastOverflowedUintDowncast(144, value);\\n }\\n return uint144(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint136 from uint256, reverting on\\n * overflow (when the input is greater than largest uint136).\\n *\\n * Counterpart to Solidity's `uint136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n */\\n function toUint136(uint256 value) internal pure returns (uint136) {\\n if (value > type(uint136).max) {\\n revert SafeCastOverflowedUintDowncast(136, value);\\n }\\n return uint136(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint128 from uint256, reverting on\\n * overflow (when the input is greater than largest uint128).\\n *\\n * Counterpart to Solidity's `uint128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n */\\n function toUint128(uint256 value) internal pure returns (uint128) {\\n if (value > type(uint128).max) {\\n revert SafeCastOverflowedUintDowncast(128, value);\\n }\\n return uint128(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint120 from uint256, reverting on\\n * overflow (when the input is greater than largest uint120).\\n *\\n * Counterpart to Solidity's `uint120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n */\\n function toUint120(uint256 value) internal pure returns (uint120) {\\n if (value > type(uint120).max) {\\n revert SafeCastOverflowedUintDowncast(120, value);\\n }\\n return uint120(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint112 from uint256, reverting on\\n * overflow (when the input is greater than largest uint112).\\n *\\n * Counterpart to Solidity's `uint112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n */\\n function toUint112(uint256 value) internal pure returns (uint112) {\\n if (value > type(uint112).max) {\\n revert SafeCastOverflowedUintDowncast(112, value);\\n }\\n return uint112(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint104 from uint256, reverting on\\n * overflow (when the input is greater than largest uint104).\\n *\\n * Counterpart to Solidity's `uint104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n */\\n function toUint104(uint256 value) internal pure returns (uint104) {\\n if (value > type(uint104).max) {\\n revert SafeCastOverflowedUintDowncast(104, value);\\n }\\n return uint104(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint96 from uint256, reverting on\\n * overflow (when the input is greater than largest uint96).\\n *\\n * Counterpart to Solidity's `uint96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n */\\n function toUint96(uint256 value) internal pure returns (uint96) {\\n if (value > type(uint96).max) {\\n revert SafeCastOverflowedUintDowncast(96, value);\\n }\\n return uint96(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint88 from uint256, reverting on\\n * overflow (when the input is greater than largest uint88).\\n *\\n * Counterpart to Solidity's `uint88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n */\\n function toUint88(uint256 value) internal pure returns (uint88) {\\n if (value > type(uint88).max) {\\n revert SafeCastOverflowedUintDowncast(88, value);\\n }\\n return uint88(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint80 from uint256, reverting on\\n * overflow (when the input is greater than largest uint80).\\n *\\n * Counterpart to Solidity's `uint80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n */\\n function toUint80(uint256 value) internal pure returns (uint80) {\\n if (value > type(uint80).max) {\\n revert SafeCastOverflowedUintDowncast(80, value);\\n }\\n return uint80(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint72 from uint256, reverting on\\n * overflow (when the input is greater than largest uint72).\\n *\\n * Counterpart to Solidity's `uint72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n */\\n function toUint72(uint256 value) internal pure returns (uint72) {\\n if (value > type(uint72).max) {\\n revert SafeCastOverflowedUintDowncast(72, value);\\n }\\n return uint72(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint64 from uint256, reverting on\\n * overflow (when the input is greater than largest uint64).\\n *\\n * Counterpart to Solidity's `uint64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n */\\n function toUint64(uint256 value) internal pure returns (uint64) {\\n if (value > type(uint64).max) {\\n revert SafeCastOverflowedUintDowncast(64, value);\\n }\\n return uint64(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint56 from uint256, reverting on\\n * overflow (when the input is greater than largest uint56).\\n *\\n * Counterpart to Solidity's `uint56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n */\\n function toUint56(uint256 value) internal pure returns (uint56) {\\n if (value > type(uint56).max) {\\n revert SafeCastOverflowedUintDowncast(56, value);\\n }\\n return uint56(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint48 from uint256, reverting on\\n * overflow (when the input is greater than largest uint48).\\n *\\n * Counterpart to Solidity's `uint48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n */\\n function toUint48(uint256 value) internal pure returns (uint48) {\\n if (value > type(uint48).max) {\\n revert SafeCastOverflowedUintDowncast(48, value);\\n }\\n return uint48(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint40 from uint256, reverting on\\n * overflow (when the input is greater than largest uint40).\\n *\\n * Counterpart to Solidity's `uint40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n */\\n function toUint40(uint256 value) internal pure returns (uint40) {\\n if (value > type(uint40).max) {\\n revert SafeCastOverflowedUintDowncast(40, value);\\n }\\n return uint40(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint32 from uint256, reverting on\\n * overflow (when the input is greater than largest uint32).\\n *\\n * Counterpart to Solidity's `uint32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n */\\n function toUint32(uint256 value) internal pure returns (uint32) {\\n if (value > type(uint32).max) {\\n revert SafeCastOverflowedUintDowncast(32, value);\\n }\\n return uint32(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint24 from uint256, reverting on\\n * overflow (when the input is greater than largest uint24).\\n *\\n * Counterpart to Solidity's `uint24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n */\\n function toUint24(uint256 value) internal pure returns (uint24) {\\n if (value > type(uint24).max) {\\n revert SafeCastOverflowedUintDowncast(24, value);\\n }\\n return uint24(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint16 from uint256, reverting on\\n * overflow (when the input is greater than largest uint16).\\n *\\n * Counterpart to Solidity's `uint16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n */\\n function toUint16(uint256 value) internal pure returns (uint16) {\\n if (value > type(uint16).max) {\\n revert SafeCastOverflowedUintDowncast(16, value);\\n }\\n return uint16(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint8 from uint256, reverting on\\n * overflow (when the input is greater than largest uint8).\\n *\\n * Counterpart to Solidity's `uint8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n */\\n function toUint8(uint256 value) internal pure returns (uint8) {\\n if (value > type(uint8).max) {\\n revert SafeCastOverflowedUintDowncast(8, value);\\n }\\n return uint8(value);\\n }\\n\\n /**\\n * @dev Converts a signed int256 into an unsigned uint256.\\n *\\n * Requirements:\\n *\\n * - input must be greater than or equal to 0.\\n */\\n function toUint256(int256 value) internal pure returns (uint256) {\\n if (value < 0) {\\n revert SafeCastOverflowedIntToUint(value);\\n }\\n return uint256(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted int248 from int256, reverting on\\n * overflow (when the input is less than smallest int248 or\\n * greater than largest int248).\\n *\\n * Counterpart to Solidity's `int248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n */\\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\\n downcasted = int248(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(248, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int240 from int256, reverting on\\n * overflow (when the input is less than smallest int240 or\\n * greater than largest int240).\\n *\\n * Counterpart to Solidity's `int240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n */\\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\\n downcasted = int240(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(240, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int232 from int256, reverting on\\n * overflow (when the input is less than smallest int232 or\\n * greater than largest int232).\\n *\\n * Counterpart to Solidity's `int232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n */\\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\\n downcasted = int232(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(232, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int224 from int256, reverting on\\n * overflow (when the input is less than smallest int224 or\\n * greater than largest int224).\\n *\\n * Counterpart to Solidity's `int224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n */\\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\\n downcasted = int224(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(224, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int216 from int256, reverting on\\n * overflow (when the input is less than smallest int216 or\\n * greater than largest int216).\\n *\\n * Counterpart to Solidity's `int216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n */\\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\\n downcasted = int216(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(216, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int208 from int256, reverting on\\n * overflow (when the input is less than smallest int208 or\\n * greater than largest int208).\\n *\\n * Counterpart to Solidity's `int208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n */\\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\\n downcasted = int208(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(208, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int200 from int256, reverting on\\n * overflow (when the input is less than smallest int200 or\\n * greater than largest int200).\\n *\\n * Counterpart to Solidity's `int200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n */\\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\\n downcasted = int200(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(200, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int192 from int256, reverting on\\n * overflow (when the input is less than smallest int192 or\\n * greater than largest int192).\\n *\\n * Counterpart to Solidity's `int192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n */\\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\\n downcasted = int192(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(192, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int184 from int256, reverting on\\n * overflow (when the input is less than smallest int184 or\\n * greater than largest int184).\\n *\\n * Counterpart to Solidity's `int184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n */\\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\\n downcasted = int184(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(184, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int176 from int256, reverting on\\n * overflow (when the input is less than smallest int176 or\\n * greater than largest int176).\\n *\\n * Counterpart to Solidity's `int176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n */\\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\\n downcasted = int176(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(176, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int168 from int256, reverting on\\n * overflow (when the input is less than smallest int168 or\\n * greater than largest int168).\\n *\\n * Counterpart to Solidity's `int168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n */\\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\\n downcasted = int168(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(168, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int160 from int256, reverting on\\n * overflow (when the input is less than smallest int160 or\\n * greater than largest int160).\\n *\\n * Counterpart to Solidity's `int160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n */\\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\\n downcasted = int160(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(160, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int152 from int256, reverting on\\n * overflow (when the input is less than smallest int152 or\\n * greater than largest int152).\\n *\\n * Counterpart to Solidity's `int152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n */\\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\\n downcasted = int152(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(152, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int144 from int256, reverting on\\n * overflow (when the input is less than smallest int144 or\\n * greater than largest int144).\\n *\\n * Counterpart to Solidity's `int144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n */\\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\\n downcasted = int144(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(144, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int136 from int256, reverting on\\n * overflow (when the input is less than smallest int136 or\\n * greater than largest int136).\\n *\\n * Counterpart to Solidity's `int136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n */\\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\\n downcasted = int136(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(136, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int128 from int256, reverting on\\n * overflow (when the input is less than smallest int128 or\\n * greater than largest int128).\\n *\\n * Counterpart to Solidity's `int128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n */\\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\\n downcasted = int128(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(128, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int120 from int256, reverting on\\n * overflow (when the input is less than smallest int120 or\\n * greater than largest int120).\\n *\\n * Counterpart to Solidity's `int120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n */\\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\\n downcasted = int120(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(120, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int112 from int256, reverting on\\n * overflow (when the input is less than smallest int112 or\\n * greater than largest int112).\\n *\\n * Counterpart to Solidity's `int112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n */\\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\\n downcasted = int112(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(112, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int104 from int256, reverting on\\n * overflow (when the input is less than smallest int104 or\\n * greater than largest int104).\\n *\\n * Counterpart to Solidity's `int104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n */\\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\\n downcasted = int104(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(104, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int96 from int256, reverting on\\n * overflow (when the input is less than smallest int96 or\\n * greater than largest int96).\\n *\\n * Counterpart to Solidity's `int96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n */\\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\\n downcasted = int96(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(96, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int88 from int256, reverting on\\n * overflow (when the input is less than smallest int88 or\\n * greater than largest int88).\\n *\\n * Counterpart to Solidity's `int88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n */\\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\\n downcasted = int88(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(88, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int80 from int256, reverting on\\n * overflow (when the input is less than smallest int80 or\\n * greater than largest int80).\\n *\\n * Counterpart to Solidity's `int80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n */\\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\\n downcasted = int80(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(80, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int72 from int256, reverting on\\n * overflow (when the input is less than smallest int72 or\\n * greater than largest int72).\\n *\\n * Counterpart to Solidity's `int72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n */\\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\\n downcasted = int72(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(72, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int64 from int256, reverting on\\n * overflow (when the input is less than smallest int64 or\\n * greater than largest int64).\\n *\\n * Counterpart to Solidity's `int64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n */\\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\\n downcasted = int64(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(64, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int56 from int256, reverting on\\n * overflow (when the input is less than smallest int56 or\\n * greater than largest int56).\\n *\\n * Counterpart to Solidity's `int56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n */\\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\\n downcasted = int56(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(56, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int48 from int256, reverting on\\n * overflow (when the input is less than smallest int48 or\\n * greater than largest int48).\\n *\\n * Counterpart to Solidity's `int48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n */\\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\\n downcasted = int48(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(48, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int40 from int256, reverting on\\n * overflow (when the input is less than smallest int40 or\\n * greater than largest int40).\\n *\\n * Counterpart to Solidity's `int40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n */\\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\\n downcasted = int40(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(40, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int32 from int256, reverting on\\n * overflow (when the input is less than smallest int32 or\\n * greater than largest int32).\\n *\\n * Counterpart to Solidity's `int32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n */\\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\\n downcasted = int32(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(32, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int24 from int256, reverting on\\n * overflow (when the input is less than smallest int24 or\\n * greater than largest int24).\\n *\\n * Counterpart to Solidity's `int24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n */\\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\\n downcasted = int24(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(24, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int16 from int256, reverting on\\n * overflow (when the input is less than smallest int16 or\\n * greater than largest int16).\\n *\\n * Counterpart to Solidity's `int16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n */\\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\\n downcasted = int16(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(16, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int8 from int256, reverting on\\n * overflow (when the input is less than smallest int8 or\\n * greater than largest int8).\\n *\\n * Counterpart to Solidity's `int8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n */\\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\\n downcasted = int8(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(8, value);\\n }\\n }\\n\\n /**\\n * @dev Converts an unsigned uint256 into a signed int256.\\n *\\n * Requirements:\\n *\\n * - input must be less than or equal to maxInt256.\\n */\\n function toInt256(uint256 value) internal pure returns (int256) {\\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\\n if (value > uint256(type(int256).max)) {\\n revert SafeCastOverflowedUintToInt(value);\\n }\\n return int256(value);\\n }\\n\\n /**\\n * @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump.\\n */\\n function toUint(bool b) internal pure returns (uint256 u) {\\n assembly (\\\"memory-safe\\\") {\\n u := iszero(iszero(b))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x195533c86d0ef72bcc06456a4f66a9b941f38eb403739b00f21fd7c1abd1ae54\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/SignedMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SignedMath.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {SafeCast} from \\\"./SafeCast.sol\\\";\\n\\n/**\\n * @dev Standard signed math utilities missing in the Solidity language.\\n */\\nlibrary SignedMath {\\n /**\\n * @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant.\\n *\\n * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone.\\n * However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute\\n * one branch when needed, making this function more expensive.\\n */\\n function ternary(bool condition, int256 a, int256 b) internal pure returns (int256) {\\n unchecked {\\n // branchless ternary works because:\\n // b ^ (a ^ b) == a\\n // b ^ 0 == b\\n return b ^ ((a ^ b) * int256(SafeCast.toUint(condition)));\\n }\\n }\\n\\n /**\\n * @dev Returns the largest of two signed numbers.\\n */\\n function max(int256 a, int256 b) internal pure returns (int256) {\\n return ternary(a > b, a, b);\\n }\\n\\n /**\\n * @dev Returns the smallest of two signed numbers.\\n */\\n function min(int256 a, int256 b) internal pure returns (int256) {\\n return ternary(a < b, a, b);\\n }\\n\\n /**\\n * @dev Returns the average of two signed numbers without overflow.\\n * The result is rounded towards zero.\\n */\\n function average(int256 a, int256 b) internal pure returns (int256) {\\n // Formula from the book \\\"Hacker's Delight\\\"\\n int256 x = (a & b) + ((a ^ b) >> 1);\\n return x + (int256(uint256(x) >> 255) & (a ^ b));\\n }\\n\\n /**\\n * @dev Returns the absolute unsigned value of a signed value.\\n */\\n function abs(int256 n) internal pure returns (uint256) {\\n unchecked {\\n // Formula from the \\\"Bit Twiddling Hacks\\\" by Sean Eron Anderson.\\n // Since `n` is a signed integer, the generated bytecode will use the SAR opcode to perform the right shift,\\n // taking advantage of the most significant (or \\\"sign\\\" bit) in two's complement representation.\\n // This opcode adds new most significant bits set to the value of the previous most significant bit. As a result,\\n // the mask will either be `bytes32(0)` (if n is positive) or `~bytes32(0)` (if n is negative).\\n int256 mask = n >> 255;\\n\\n // A `bytes32(0)` mask leaves the input unchanged, while a `~bytes32(0)` mask complements it.\\n return uint256((n + mask) ^ mask);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xb1970fac7b64e6c09611e6691791e848d5e3fe410fa5899e7df2e0afd77a99e3\",\"license\":\"MIT\"},\"src/EscrowUniversal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\n/// @authors: [@unknownunknown1, @jaybuidl]\\n/// @reviewers: []\\n/// @auditors: []\\n/// @bounties: []\\n\\npragma solidity 0.8.24;\\n\\nimport {IArbitrableV2, IArbitratorV2} from \\\"@kleros/kleros-v2-contracts/arbitration/interfaces/IArbitrableV2.sol\\\";\\nimport \\\"@kleros/kleros-v2-contracts/arbitration/interfaces/IDisputeTemplateRegistry.sol\\\";\\nimport {SafeERC20, IERC20} from \\\"./libraries/SafeERC20.sol\\\";\\nimport \\\"./interfaces/IEscrow.sol\\\";\\n\\n/// @title EscrowUniversal for a sale paid in native currency or ERC20 tokens without platform fees.\\n/// @dev Adapted from MultipleArbitrableTokenTransaction contract: https://github.com/kleros/kleros-interaction/blob/master/contracts/standard/arbitration/MultipleArbitrableTokenTransaction.sol\\n/// and from MultipleArbitrableTransaction contract: https://github.com/kleros/kleros-interaction/blob/master/contracts/standard/arbitration/MultipleArbitrableTransaction.sol\\n/// Note that the contract expects the tokens to have standard ERC20 behaviour.\\n/// The tokens that don't conform to this type of behaviour should be filtered by the UI.\\n/// Tokens should not reenter or allow recipients to refuse the transfer.\\n/// Also note that arbitration fees are still paid in ETH.\\ncontract EscrowUniversal is IEscrow, IArbitrableV2 {\\n // Use safe transfers when both parties are paid simultaneously (save for acceptSettlement) to prevent griefing.\\n using SafeERC20 for IERC20;\\n\\n // ************************************* //\\n // * Storage * //\\n // ************************************* //\\n\\n uint256 public constant AMOUNT_OF_CHOICES = 2;\\n address public governor;\\n IArbitratorV2 public arbitrator; // Address of the arbitrator contract.\\n bytes public arbitratorExtraData; // Extra data to set up the arbitration.\\n IDisputeTemplateRegistry public templateRegistry; // The dispute template registry.\\n uint256 public templateId; // The current dispute template identifier.\\n uint256 public feeTimeout; // Time in seconds a party can take to pay arbitration fees before being considered unresponsive and lose the dispute.\\n uint256 public settlementTimeout; // Time in seconds a party can take to accept or propose a settlement before being considered unresponsive.\\n Transaction[] public transactions; // List of all created transactions.\\n mapping(uint256 => uint256) public disputeIDtoTransactionID; // Naps dispute ID to tx ID.\\n mapping(IERC20 => uint256) public amountCaps; // Caps the amount of the respective token for the Escrow transaction.\\n\\n // ************************************* //\\n // * Function Modifiers * //\\n // ************************************* //\\n\\n modifier onlyByGovernor() {\\n if (governor != msg.sender) revert GovernorOnly();\\n _;\\n }\\n\\n modifier shouldNotExceedCap(IERC20 _token, uint256 _amount) {\\n if (_amount > amountCaps[_token]) revert AmountExceedsCap();\\n _;\\n }\\n\\n // ************************************* //\\n // * Constructor * //\\n // ************************************* //\\n\\n /// @dev Constructor.\\n /// @param _arbitrator The arbitrator of the contract.\\n /// @param _arbitratorExtraData Extra data for the arbitrator.\\n /// @param _templateData The dispute template data.\\n /// @param _templateDataMappings The dispute template data mappings.\\n /// @param _templateRegistry The dispute template registry.\\n /// @param _feeTimeout Arbitration fee timeout for the parties.\\n /// @param _settlementTimeout Settlement timeout for the parties.\\n constructor(\\n IArbitratorV2 _arbitrator,\\n bytes memory _arbitratorExtraData,\\n string memory _templateData,\\n string memory _templateDataMappings,\\n IDisputeTemplateRegistry _templateRegistry,\\n uint256 _feeTimeout,\\n uint256 _settlementTimeout\\n ) {\\n governor = msg.sender;\\n arbitrator = _arbitrator;\\n arbitratorExtraData = _arbitratorExtraData;\\n templateRegistry = _templateRegistry;\\n feeTimeout = _feeTimeout;\\n settlementTimeout = _settlementTimeout;\\n templateId = templateRegistry.setDisputeTemplate(\\\"\\\", _templateData, _templateDataMappings);\\n\\n emit ParameterUpdated(_feeTimeout, _settlementTimeout, _arbitratorExtraData);\\n }\\n\\n // ************************************* //\\n // * Governance * //\\n // ************************************* //\\n\\n function changeGovernor(address _governor) external onlyByGovernor {\\n governor = _governor;\\n }\\n\\n function changeArbitrator(IArbitratorV2 _arbitrator) external onlyByGovernor {\\n arbitrator = _arbitrator;\\n }\\n\\n function changeArbitratorExtraData(bytes calldata _arbitratorExtraData) external onlyByGovernor {\\n arbitratorExtraData = _arbitratorExtraData;\\n emit ParameterUpdated(feeTimeout, settlementTimeout, _arbitratorExtraData);\\n }\\n\\n function changeTemplateRegistry(IDisputeTemplateRegistry _templateRegistry) external onlyByGovernor {\\n templateRegistry = _templateRegistry;\\n }\\n\\n function changeDisputeTemplate(\\n string memory _templateData,\\n string memory _templateDataMappings\\n ) external onlyByGovernor {\\n templateId = templateRegistry.setDisputeTemplate(\\\"\\\", _templateData, _templateDataMappings);\\n }\\n\\n function changeFeeTimeout(uint256 _feeTimeout) external onlyByGovernor {\\n feeTimeout = _feeTimeout;\\n emit ParameterUpdated(_feeTimeout, settlementTimeout, arbitratorExtraData);\\n }\\n\\n function changeSettlementTimeout(uint256 _settlementTimeout) external onlyByGovernor {\\n settlementTimeout = _settlementTimeout;\\n emit ParameterUpdated(feeTimeout, _settlementTimeout, arbitratorExtraData);\\n }\\n\\n function changeAmountCap(IERC20 _token, uint256 _amountCap) external onlyByGovernor {\\n amountCaps[_token] = _amountCap;\\n }\\n\\n // ************************************* //\\n // * State Modifiers * //\\n // ************************************* //\\n\\n /// @inheritdoc IEscrow\\n function createNativeTransaction(\\n uint256 _deadline,\\n string memory _transactionUri,\\n address payable _seller\\n ) external payable override shouldNotExceedCap(NATIVE, msg.value) returns (uint256 transactionID) {\\n Transaction storage transaction = transactions.push();\\n transaction.buyer = payable(msg.sender);\\n transaction.seller = _seller;\\n transaction.amount = msg.value;\\n transaction.token = NATIVE;\\n transaction.deadline = _deadline;\\n\\n transactionID = transactions.length - 1;\\n\\n emit NativeTransactionCreated(\\n transactionID,\\n _transactionUri,\\n msg.sender,\\n _seller,\\n msg.value,\\n transaction.deadline\\n );\\n }\\n\\n /// @inheritdoc IEscrow\\n function createERC20Transaction(\\n uint256 _amount,\\n IERC20 _token,\\n uint256 _deadline,\\n string memory _transactionUri,\\n address payable _seller\\n ) external override shouldNotExceedCap(_token, _amount) returns (uint256 transactionID) {\\n // Transfers token from sender wallet to contract.\\n if (!_token.safeTransferFrom(msg.sender, address(this), _amount)) revert TokenTransferFailed();\\n Transaction storage transaction = transactions.push();\\n transaction.buyer = payable(msg.sender);\\n transaction.seller = _seller;\\n transaction.amount = _amount;\\n transaction.token = _token;\\n transaction.deadline = _deadline;\\n\\n transactionID = transactions.length - 1;\\n\\n emit ERC20TransactionCreated(\\n transactionID,\\n _transactionUri,\\n msg.sender,\\n _seller,\\n _token,\\n _amount,\\n transaction.deadline\\n );\\n }\\n\\n /// @inheritdoc IEscrow\\n function pay(uint256 _transactionID, uint256 _amount) external override {\\n Transaction storage transaction = transactions[_transactionID];\\n if (transaction.buyer != msg.sender) revert BuyerOnly();\\n if (transaction.status != Status.NoDispute) revert TransactionDisputed();\\n if (_amount > transaction.amount) revert MaximumPaymentAmountExceeded();\\n\\n emit Payment(_transactionID, _amount, transaction.buyer);\\n\\n transaction.amount -= _amount;\\n if (transaction.amount == 0) {\\n transaction.status = Status.TransactionResolved;\\n emit TransactionResolved(_transactionID, Resolution.TransactionExecuted);\\n }\\n\\n if (transaction.token == NATIVE) {\\n transaction.seller.send(_amount); // It is the user responsibility to accept ETH.\\n } else {\\n if (!transaction.token.safeTransfer(transaction.seller, _amount)) revert TokenTransferFailed();\\n }\\n }\\n\\n /// @inheritdoc IEscrow\\n function reimburse(uint256 _transactionID, uint256 _amountReimbursed) external override {\\n Transaction storage transaction = transactions[_transactionID];\\n if (transaction.seller != msg.sender) revert SellerOnly();\\n if (transaction.status != Status.NoDispute) revert TransactionDisputed();\\n if (_amountReimbursed > transaction.amount) revert MaximumPaymentAmountExceeded();\\n\\n emit Payment(_transactionID, _amountReimbursed, transaction.seller);\\n\\n transaction.amount -= _amountReimbursed;\\n if (transaction.amount == 0) {\\n transaction.status = Status.TransactionResolved;\\n emit TransactionResolved(_transactionID, Resolution.TransactionExecuted);\\n }\\n\\n if (transaction.token == NATIVE) {\\n transaction.buyer.send(_amountReimbursed); // It is the user responsibility to accept ETH.\\n } else {\\n if (!transaction.token.safeTransfer(transaction.buyer, _amountReimbursed)) revert TokenTransferFailed();\\n }\\n }\\n\\n /// @inheritdoc IEscrow\\n function executeTransaction(uint256 _transactionID) external override {\\n Transaction storage transaction = transactions[_transactionID];\\n if (block.timestamp < transaction.deadline) revert DeadlineNotPassed();\\n if (transaction.status != Status.NoDispute) revert TransactionDisputed();\\n\\n uint256 amount = transaction.amount;\\n transaction.amount = 0;\\n transaction.status = Status.TransactionResolved;\\n\\n if (transaction.token == NATIVE) {\\n transaction.seller.send(amount); // It is the user responsibility to accept ETH.\\n } else {\\n if (!transaction.token.safeTransfer(transaction.seller, amount)) revert TokenTransferFailed();\\n }\\n\\n emit Payment(_transactionID, amount, transaction.buyer);\\n emit TransactionResolved(_transactionID, Resolution.TransactionExecuted);\\n }\\n\\n /// @inheritdoc IEscrow\\n function proposeSettlement(uint256 _transactionID, uint256 _amount) external override {\\n Transaction storage transaction = transactions[_transactionID];\\n if (transaction.status == Status.NoDispute && block.timestamp >= transaction.deadline)\\n revert TransactionExpired();\\n if (transaction.status >= Status.WaitingBuyer) revert TransactionEscalatedForArbitration();\\n if (_amount > transaction.amount) revert MaximumPaymentAmountExceeded();\\n\\n Party party;\\n transaction.lastFeePaymentTime = block.timestamp;\\n if (transaction.status == Status.WaitingSettlementBuyer) {\\n if (msg.sender != transaction.buyer) revert BuyerOnly();\\n transaction.settlementBuyer = _amount;\\n transaction.status = Status.WaitingSettlementSeller;\\n party = Party.Buyer;\\n } else if (transaction.status == Status.WaitingSettlementSeller) {\\n if (msg.sender != transaction.seller) revert SellerOnly();\\n transaction.settlementSeller = _amount;\\n transaction.status = Status.WaitingSettlementBuyer;\\n party = Party.Seller;\\n } else {\\n if (msg.sender == transaction.buyer) {\\n transaction.settlementBuyer = _amount;\\n transaction.status = Status.WaitingSettlementSeller;\\n party = Party.Buyer;\\n } else if (msg.sender == transaction.seller) {\\n transaction.settlementSeller = _amount;\\n transaction.status = Status.WaitingSettlementBuyer;\\n party = Party.Seller;\\n } else revert BuyerOrSellerOnly();\\n }\\n emit SettlementProposed(_transactionID, party, _amount);\\n }\\n\\n /// @inheritdoc IEscrow\\n function acceptSettlement(uint256 _transactionID) external override {\\n Transaction storage transaction = transactions[_transactionID];\\n uint256 settlementAmount;\\n if (transaction.status == Status.WaitingSettlementBuyer) {\\n if (msg.sender != transaction.buyer) revert BuyerOnly();\\n settlementAmount = transaction.settlementSeller;\\n } else if (transaction.status == Status.WaitingSettlementSeller) {\\n if (msg.sender != transaction.seller) revert SellerOnly();\\n settlementAmount = transaction.settlementBuyer;\\n } else revert NoSettlementProposedOrTransactionMovedOnAcceptSettlement();\\n\\n uint256 remainingAmount = transaction.amount - settlementAmount;\\n\\n transaction.amount = 0;\\n transaction.settlementBuyer = 0;\\n transaction.settlementSeller = 0;\\n transaction.status = Status.TransactionResolved;\\n\\n if (transaction.token == NATIVE) {\\n // It is the users' responsibility to accept ETH.\\n transaction.buyer.send(remainingAmount);\\n transaction.seller.send(settlementAmount);\\n } else {\\n transaction.token.safeTransfer(transaction.buyer, remainingAmount);\\n transaction.token.safeTransfer(transaction.seller, settlementAmount);\\n }\\n\\n emit TransactionResolved(_transactionID, Resolution.SettlementReached);\\n }\\n\\n /// @inheritdoc IEscrow\\n function payArbitrationFeeByBuyer(uint256 _transactionID) external payable override {\\n Transaction storage transaction = transactions[_transactionID];\\n if (\\n transaction.status != Status.WaitingSettlementBuyer &&\\n transaction.status != Status.WaitingSettlementSeller &&\\n transaction.status != Status.WaitingBuyer\\n ) revert NoSettlementProposedOrTransactionMovedOnPayFeeBuyer();\\n\\n // Allow the other party enough time to respond to a settlement before allowing the proposer to raise a dispute.\\n if (\\n transaction.status == Status.WaitingSettlementSeller &&\\n block.timestamp - transaction.lastFeePaymentTime < settlementTimeout\\n ) revert SettlementPeriodNotOver();\\n\\n if (msg.sender != transaction.buyer) revert BuyerOnly();\\n\\n transaction.buyerFee += msg.value;\\n uint256 arbitrationCost = arbitrator.arbitrationCost(arbitratorExtraData);\\n if (transaction.buyerFee < arbitrationCost) revert BuyerFeeNotCoverArbitrationCosts();\\n\\n transaction.lastFeePaymentTime = block.timestamp;\\n\\n if (transaction.sellerFee < arbitrationCost) {\\n // The seller still has to pay. This can also happen if he has paid, but arbitrationCost has increased.\\n transaction.status = Status.WaitingSeller;\\n emit HasToPayFee(_transactionID, Party.Seller);\\n } else {\\n // The seller has also paid the fee. We create the dispute.\\n raiseDispute(_transactionID, arbitrationCost);\\n }\\n }\\n\\n /// @inheritdoc IEscrow\\n function payArbitrationFeeBySeller(uint256 _transactionID) external payable override {\\n Transaction storage transaction = transactions[_transactionID];\\n if (\\n transaction.status != Status.WaitingSettlementBuyer &&\\n transaction.status != Status.WaitingSettlementSeller &&\\n transaction.status != Status.WaitingSeller\\n ) revert NoSettlementProposedOrTransactionMovedOnPayFeeSeller();\\n\\n // Allow the other party enough time to respond to a settlement before allowing the proposer to raise a dispute.\\n if (\\n transaction.status == Status.WaitingSettlementBuyer &&\\n block.timestamp - transaction.lastFeePaymentTime < settlementTimeout\\n ) revert SettlementPeriodNotOver();\\n\\n if (msg.sender != transaction.seller) revert SellerOnly();\\n\\n transaction.sellerFee += msg.value;\\n uint256 arbitrationCost = arbitrator.arbitrationCost(arbitratorExtraData);\\n if (transaction.sellerFee < arbitrationCost) revert SellerFeeNotCoverArbitrationCosts();\\n\\n transaction.lastFeePaymentTime = block.timestamp;\\n\\n if (transaction.buyerFee < arbitrationCost) {\\n // The buyer still has to pay. This can also happen if he has paid, but arbitrationCost has increased.\\n transaction.status = Status.WaitingBuyer;\\n emit HasToPayFee(_transactionID, Party.Buyer);\\n } else {\\n // The buyer has also paid the fee. We create the dispute.\\n raiseDispute(_transactionID, arbitrationCost);\\n }\\n }\\n\\n /// @inheritdoc IEscrow\\n function timeOutByBuyer(uint256 _transactionID) external override {\\n Transaction storage transaction = transactions[_transactionID];\\n if (transaction.status != Status.WaitingSeller) revert NotWaitingForSellerFees();\\n if (block.timestamp - transaction.lastFeePaymentTime < feeTimeout) revert TimeoutNotPassed();\\n\\n uint256 amount = transaction.sellerFee;\\n transaction.sellerFee = 0;\\n\\n executeRuling(_transactionID, uint256(Party.Buyer));\\n\\n if (amount != 0) {\\n transaction.seller.send(amount); // It is the user responsibility to accept ETH.\\n }\\n\\n emit TransactionResolved(_transactionID, Resolution.TimeoutByBuyer);\\n }\\n\\n /// @inheritdoc IEscrow\\n function timeOutBySeller(uint256 _transactionID) external override {\\n Transaction storage transaction = transactions[_transactionID];\\n if (transaction.status != Status.WaitingBuyer) revert NotWaitingForBuyerFees();\\n if (block.timestamp - transaction.lastFeePaymentTime < feeTimeout) revert TimeoutNotPassed();\\n\\n uint256 amount = transaction.buyerFee;\\n transaction.buyerFee = 0;\\n\\n executeRuling(_transactionID, uint256(Party.Seller));\\n\\n if (amount != 0) {\\n transaction.buyer.send(amount); // It is the user responsibility to accept ETH.\\n }\\n\\n emit TransactionResolved(_transactionID, Resolution.TimeoutBySeller);\\n }\\n\\n /// @inheritdoc IArbitrableV2\\n function rule(uint256 _disputeID, uint256 _ruling) external override {\\n if (msg.sender != address(arbitrator)) revert ArbitratorOnly();\\n if (_ruling > AMOUNT_OF_CHOICES) revert InvalidRuling();\\n\\n uint256 transactionID = disputeIDtoTransactionID[_disputeID];\\n Transaction storage transaction = transactions[transactionID];\\n if (transaction.status != Status.DisputeCreated) revert DisputeAlreadyResolved();\\n\\n emit Ruling(arbitrator, _disputeID, _ruling);\\n emit TransactionResolved(transactionID, Resolution.RulingEnforced);\\n executeRuling(transactionID, _ruling);\\n }\\n\\n // ************************************* //\\n // * Internal * //\\n // ************************************* //\\n\\n /// @dev Create a dispute.\\n /// @param _transactionID The index of the transaction.\\n /// @param _arbitrationCost Amount to pay the arbitrator.\\n function raiseDispute(uint256 _transactionID, uint256 _arbitrationCost) internal {\\n Transaction storage transaction = transactions[_transactionID];\\n transaction.status = Status.DisputeCreated;\\n transaction.disputeID = arbitrator.createDispute{value: _arbitrationCost}(\\n AMOUNT_OF_CHOICES,\\n arbitratorExtraData\\n );\\n disputeIDtoTransactionID[transaction.disputeID] = _transactionID;\\n emit DisputeRequest(arbitrator, transaction.disputeID, _transactionID, templateId, \\\"\\\");\\n\\n // Refund buyer if he overpaid.\\n if (transaction.buyerFee > _arbitrationCost) {\\n uint256 extraFeeBuyer = transaction.buyerFee - _arbitrationCost;\\n transaction.buyerFee = _arbitrationCost;\\n transaction.buyer.send(extraFeeBuyer); // It is the user responsibility to accept ETH.\\n }\\n\\n // Refund seller if he overpaid.\\n if (transaction.sellerFee > _arbitrationCost) {\\n uint256 extraFeeSeller = transaction.sellerFee - _arbitrationCost;\\n transaction.sellerFee = _arbitrationCost;\\n transaction.seller.send(extraFeeSeller); // It is the user responsibility to accept ETH.\\n }\\n }\\n\\n /// @dev Execute a ruling of a dispute. It reimburses the fee to the winning party.\\n /// @param _transactionID The index of the transaction.\\n /// @param _ruling Ruling given by the arbitrator. 1 : Reimburse the seller. 2 : Pay the buyer.\\n function executeRuling(uint256 _transactionID, uint256 _ruling) internal {\\n Transaction storage transaction = transactions[_transactionID];\\n address payable buyer = transaction.buyer;\\n address payable seller = transaction.seller;\\n\\n (uint256 buyerPayout, uint256 buyerPayoutToken, uint256 sellerPayout, uint256 sellerPayoutToken) = getPayouts(\\n _transactionID,\\n Party(_ruling)\\n );\\n\\n transaction.amount = 0;\\n transaction.settlementBuyer = 0;\\n transaction.settlementSeller = 0;\\n transaction.buyerFee = 0;\\n transaction.sellerFee = 0;\\n transaction.status = Status.TransactionResolved;\\n\\n if (buyerPayout > 0) {\\n buyer.send(buyerPayout); // It is the user responsibility to accept ETH.\\n }\\n if (sellerPayout > 0) {\\n seller.send(sellerPayout); // It is the user responsibility to accept ETH.\\n }\\n if (buyerPayoutToken > 0) {\\n transaction.token.safeTransfer(buyer, buyerPayoutToken); // Tokens should not reenter or allow recipients to refuse the transfer.\\n }\\n if (sellerPayoutToken > 0) {\\n transaction.token.safeTransfer(seller, sellerPayoutToken); // Tokens should not reenter or allow recipients to refuse the transfer.\\n }\\n }\\n\\n // ************************************* //\\n // * Public Views * //\\n // ************************************* //\\n\\n /// @inheritdoc IEscrow\\n function getTransactionCount() external view override returns (uint256) {\\n return transactions.length;\\n }\\n\\n /// @dev Get the payout depending on the winning party.\\n /// @dev The cost for the buyer is the seller payout non-inclusive of any arbitration fees.\\n /// @param _transactionID The index of the transaction.\\n /// @param _winningParty The winning party.\\n /// @return buyerPayout The payout for the buyer.\\n /// @return buyerPayoutToken The payout for the buyer in tokens.\\n /// @return sellerPayout The payout for the seller.\\n /// @return sellerPayoutToken The payout for the seller in tokens.\\n function getPayouts(\\n uint256 _transactionID,\\n Party _winningParty\\n )\\n public\\n view\\n returns (uint256 buyerPayout, uint256 buyerPayoutToken, uint256 sellerPayout, uint256 sellerPayoutToken)\\n {\\n Transaction storage transaction = transactions[_transactionID];\\n uint256 amount = transaction.amount;\\n uint256 settlementBuyer = transaction.settlementBuyer;\\n uint256 settlementSeller = transaction.settlementSeller;\\n uint256 buyerFee = transaction.buyerFee;\\n uint256 sellerFee = transaction.sellerFee;\\n bool nativePayment = transaction.token == NATIVE;\\n if (_winningParty == Party.Buyer) {\\n // The Seller gets the settlement amount proposed by the Buyer if any, otherwise nothing.\\n // The Buyer gets the remaining amount of the transaction back if any.\\n // The Buyer gets the arbitration fee back.\\n uint256 settledAmount = settlementBuyer;\\n if (nativePayment) {\\n buyerPayout = buyerFee + amount - settledAmount;\\n sellerPayout = settledAmount;\\n } else {\\n buyerPayout = buyerFee;\\n buyerPayoutToken = amount - settledAmount;\\n sellerPayoutToken = settledAmount;\\n }\\n } else if (_winningParty == Party.Seller) {\\n // The Seller gets his proposed settlement amount if any, otherwise the transaction amount.\\n // The Buyer gets the remaining amount of the transaction back if any.\\n // The Seller gets the arbitration fee back.\\n uint256 settledAmount = settlementSeller != 0 ? settlementSeller : amount;\\n if (nativePayment) {\\n buyerPayout = amount - settledAmount;\\n sellerPayout = sellerFee + settledAmount;\\n } else {\\n buyerPayoutToken = amount - settledAmount;\\n sellerPayout = sellerFee;\\n sellerPayoutToken = settledAmount;\\n }\\n } else {\\n // No party wins, we split the arbitration fee and the transaction amount.\\n // The arbitration fee has been paid twice, once by the Buyer and once by the Seller in equal amount once arbitration starts.\\n // In case of an uneven token amount, one basic token unit can be burnt.\\n uint256 splitArbitrationFee = buyerFee / 2; // buyerFee equals sellerFee.\\n buyerPayout = splitArbitrationFee;\\n sellerPayout = splitArbitrationFee;\\n uint256 splitAmount = amount / 2;\\n if (nativePayment) {\\n buyerPayout += splitAmount;\\n sellerPayout += splitAmount;\\n } else {\\n buyerPayoutToken = splitAmount;\\n sellerPayoutToken = splitAmount;\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xbcd7fe39d1afba3d14cedaffe8449f284e48595808aa33e1fd08be0b933f97fc\",\"license\":\"MIT\"},\"src/EscrowView.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.8.24;\\n\\nimport {Strings} from \\\"@openzeppelin/contracts/utils/Strings.sol\\\";\\nimport {IERC20Metadata} from \\\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\\\";\\nimport {EscrowUniversal, Transaction, NATIVE, Party, Status, IERC20} from \\\"./EscrowUniversal.sol\\\";\\n\\n/// @title EscrowView\\n/// @notice A view contract for EscrowUniversal to facilitate the display of ruling options.\\ncontract EscrowView {\\n EscrowUniversal public immutable escrow;\\n\\n /// @notice Initialize the view contract with the address of the EscrowUniversal contract.\\n /// @param _escrow The address of the EscrowUniversal contract.\\n constructor(address _escrow) {\\n escrow = EscrowUniversal(_escrow);\\n }\\n\\n /// @notice Get the payout messages for a transaction *once* a dispute is created.\\n /// @notice The amounts are exclusive of arbitration fees for clarity.\\n /// @notice The amounts pre-dispute are imprecise as the arbitration fees are not paid yet by either or both parties.\\n /// @return noWinner The payout message for the case where nobody wins.\\n /// @return buyerWins The payout message for the case where the buyer wins.\\n /// @return sellerWins The payout message for the case where the seller wins.\\n function getPayoutMessages(\\n uint256 _transactionID\\n ) external view returns (string memory noWinner, string memory buyerWins, string memory sellerWins) {\\n (, , uint256 amount, , , , , uint256 buyerFee, uint256 sellerFee, , , IERC20 token) = escrow.transactions(\\n _transactionID\\n );\\n\\n (uint256 noWinnerPayout, uint256 noWinnerPayoutToken, , ) = escrow.getPayouts(_transactionID, Party.None);\\n (, , uint256 buyerWinsCost, uint256 buyerWinsCostToken) = escrow.getPayouts(_transactionID, Party.Buyer);\\n (, , uint256 sellerWinsCost, uint256 sellerWinsCostToken) = escrow.getPayouts(_transactionID, Party.Seller);\\n\\n if (token == NATIVE) {\\n string memory amountStr = formatEth(amount);\\n noWinner = string.concat(\\n \\\"Buyer and Seller get \\\",\\n formatEth(noWinnerPayout - (buyerFee / 2)),\\n \\\" back and half of the arbitration fees.\\\"\\n );\\n string memory insteadStr = buyerWinsCost != amount ? string.concat(\\\" instead of \\\", amountStr) : \\\"\\\";\\n buyerWins = string.concat(\\n \\\"Buyer pays \\\",\\n formatEth(buyerWinsCost), // Exclusive of arbitration fees\\n insteadStr,\\n \\\", gets the arbitration fees back.\\\"\\n );\\n insteadStr = sellerWinsCost - sellerFee != amount ? string.concat(\\\" instead of \\\", amountStr) : \\\"\\\";\\n sellerWins = string.concat(\\n \\\"Buyer pays \\\",\\n formatEth(sellerWinsCost - sellerFee), // Including of arbitration fees, deduct them\\n insteadStr,\\n \\\", Seller gets the arbitration fees back.\\\"\\n );\\n } else {\\n string memory amountTokenStr = formatToken(amount, address(token));\\n noWinner = string.concat(\\n \\\"Buyer and Seller get \\\",\\n formatToken(noWinnerPayoutToken, address(token)),\\n \\\" back and half of the arbitration fees.\\\"\\n );\\n string memory insteadStr = buyerWinsCost != amount ? string.concat(\\\" instead of \\\", amountTokenStr) : \\\"\\\";\\n buyerWins = string.concat(\\n \\\"Buyer pays \\\",\\n formatToken(buyerWinsCostToken, address(token)),\\n insteadStr,\\n \\\", gets the arbitration fees back.\\\"\\n );\\n insteadStr = sellerWinsCost - sellerFee != amount ? string.concat(\\\" instead of \\\", amountTokenStr) : \\\"\\\";\\n sellerWins = string.concat(\\n \\\"Buyer pays \\\",\\n formatToken(sellerWinsCostToken, address(token)),\\n insteadStr,\\n \\\", Seller gets the arbitration fees back.\\\"\\n );\\n }\\n }\\n\\n /// @notice Format an amount in ETH to 3 decimal places.\\n /// @param _amountWei The amount in wei.\\n /// @return The formatted amount.\\n function formatEth(uint256 _amountWei) public pure returns (string memory) {\\n uint256 ethWhole = _amountWei / 1 ether;\\n uint256 ethFraction = (_amountWei % 1 ether) / 1e15; // Get the first 3 decimal digits\\n\\n // Convert the whole and fractional parts to strings\\n string memory ethWholeStr = Strings.toString(ethWhole);\\n\\n // If the fractional part is zero, return only the whole part\\n if (ethFraction == 0) {\\n return string.concat(ethWholeStr, \\\" ETH\\\");\\n }\\n\\n // Convert the fractional part to string with leading zeros if necessary\\n string memory ethFractionStr = Strings.toString(ethFraction);\\n\\n // Pad the fractional part with leading zeros to ensure three digits\\n while (bytes(ethFractionStr).length < 3) {\\n ethFractionStr = string.concat(\\\"0\\\", ethFractionStr);\\n }\\n\\n // Remove trailing zeros from the fractional part\\n bytes memory fractionBytes = bytes(ethFractionStr);\\n uint256 fractionLength = fractionBytes.length;\\n while (fractionLength > 0 && fractionBytes[fractionLength - 1] == \\\"0\\\") {\\n fractionLength--;\\n }\\n\\n if (fractionLength == 0) {\\n return ethWholeStr;\\n } else {\\n bytes memory fractionTrimmed = new bytes(fractionLength);\\n for (uint256 i = 0; i < fractionLength; i++) {\\n fractionTrimmed[i] = fractionBytes[i];\\n }\\n return string.concat(ethWholeStr, \\\".\\\", string(fractionTrimmed), \\\" ETH\\\");\\n }\\n }\\n\\n /// @notice Format an amount in a token to 3 decimal places.\\n /// @param _amountWei The amount in wei.\\n /// @param _token The address of the token.\\n /// @return The formatted amount.\\n function formatToken(uint256 _amountWei, address _token) public view returns (string memory) {\\n require(_token != address(0), \\\"Invalid token address\\\");\\n IERC20Metadata token = IERC20Metadata(_token);\\n uint8 decimals = token.decimals();\\n string memory symbol = token.symbol();\\n\\n uint256 tenToDecimals = uint256(10) ** uint256(decimals);\\n uint256 tokenWhole = _amountWei / tenToDecimals;\\n\\n uint256 tokenFraction;\\n uint8 fractionDigits;\\n\\n if (decimals >= 3) {\\n uint256 divider = uint256(10) ** uint256(decimals - 3);\\n tokenFraction = (_amountWei % tenToDecimals) / divider;\\n fractionDigits = 3;\\n } else {\\n tokenFraction = _amountWei % tenToDecimals;\\n fractionDigits = decimals;\\n }\\n\\n string memory tokenWholeStr = Strings.toString(tokenWhole);\\n\\n if (tokenFraction == 0) {\\n return string.concat(tokenWholeStr, \\\" \\\", symbol);\\n }\\n\\n string memory tokenFractionStr = Strings.toString(tokenFraction);\\n\\n while (bytes(tokenFractionStr).length < fractionDigits) {\\n tokenFractionStr = string.concat(\\\"0\\\", tokenFractionStr);\\n }\\n\\n bytes memory fractionBytes = bytes(tokenFractionStr);\\n uint256 fractionLength = fractionBytes.length;\\n while (fractionLength > 0 && fractionBytes[fractionLength - 1] == bytes1(\\\"0\\\")) {\\n fractionLength--;\\n }\\n\\n if (fractionLength == 0) {\\n return string.concat(tokenWholeStr, \\\" \\\", symbol);\\n } else {\\n bytes memory fractionTrimmed = new bytes(fractionLength);\\n for (uint256 i = 0; i < fractionLength; i++) {\\n fractionTrimmed[i] = fractionBytes[i];\\n }\\n return string.concat(tokenWholeStr, \\\".\\\", string(fractionTrimmed), \\\" \\\", symbol);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xada50eda8604942b4d5e4c19de3aee0fe69cb611b9f9fcc13612669072b152a4\",\"license\":\"MIT\"},\"src/interfaces/IEscrow.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.8.24;\\n\\nimport \\\"./Types.sol\\\";\\n\\ninterface IEscrow {\\n // ************************************* //\\n // * Events * //\\n // ************************************* //\\n\\n /// @dev To be emitted when Escrow parameters are updated.\\n event ParameterUpdated(uint256 _feeTimeout, uint256 _settlementTimeout, bytes _arbitratorExtraData);\\n\\n /// @dev To be emitted when a party pays or reimburses the other.\\n /// @param _transactionID The index of the transaction.\\n /// @param _amount The amount paid.\\n /// @param _party The party that paid.\\n event Payment(uint256 indexed _transactionID, uint256 _amount, address _party);\\n\\n /// @dev Indicate that a party has to pay a fee or would otherwise be considered as losing.\\n /// @param _transactionID The index of the transaction.\\n /// @param _party The party who has to pay.\\n event HasToPayFee(uint256 indexed _transactionID, Party _party);\\n\\n /// @dev Emitted when a party proposes a settlement.\\n /// @param _transactionID The index of the transaction.\\n /// @param _party The party that proposed a settlement.\\n /// @param _amount The amount proposed.\\n event SettlementProposed(uint256 indexed _transactionID, Party _party, uint256 _amount);\\n\\n /// @dev Emitted when a transaction paid in native currency is created.\\n /// @param _transactionID The index of the transaction.\\n /// @param _transactionUri The IPFS Uri Hash of the transaction.\\n /// @param _buyer The address of the buyer.\\n /// @param _seller The address of the seller.\\n /// @param _amount The initial amount in the transaction.\\n /// @param _deadline The deadline of the transaction.\\n event NativeTransactionCreated(\\n uint256 indexed _transactionID,\\n string _transactionUri,\\n address indexed _buyer,\\n address indexed _seller,\\n uint256 _amount,\\n uint256 _deadline\\n );\\n\\n /// @dev Emitted when a transaction paid in ERC20 token is created.\\n /// @param _transactionID The index of the transaction.\\n /// @param _transactionUri The IPFS Uri Hash of the transaction.\\n /// @param _buyer The address of the buyer.\\n /// @param _seller The address of the seller.\\n /// @param _token The token address.\\n /// @param _amount The initial amount in the transaction.\\n /// @param _deadline The deadline of the transaction.\\n event ERC20TransactionCreated(\\n uint256 indexed _transactionID,\\n string _transactionUri,\\n address indexed _buyer,\\n address indexed _seller,\\n IERC20 _token,\\n uint256 _amount,\\n uint256 _deadline\\n );\\n\\n /// @dev To be emitted when a transaction is resolved, either by its\\n /// execution, a timeout or because a ruling was enforced.\\n /// @param _transactionID The ID of the respective transaction.\\n /// @param _resolution Short description of what caused the transaction to be solved.\\n event TransactionResolved(uint256 indexed _transactionID, Resolution indexed _resolution);\\n\\n // ************************************* //\\n // * State Modifiers * //\\n // ************************************* //\\n\\n /// @dev Create a transaction.\\n /// @param _deadline Time after which a party can automatically execute the arbitrable transaction.\\n /// @param _transactionUri The IPFS Uri Hash of the transaction.\\n /// @param _seller The recipient of the transaction.\\n /// @return transactionID The index of the transaction.\\n function createNativeTransaction(\\n uint256 _deadline,\\n string memory _transactionUri,\\n address payable _seller\\n ) external payable returns (uint256 transactionID);\\n\\n /// @dev Create a transaction.\\n /// @param _amount The amount of tokens in this transaction.\\n /// @param _token The ERC20 token contract.\\n /// @param _deadline Time after which a party can automatically execute the arbitrable transaction.\\n /// @param _transactionUri The IPFS Uri Hash of the transaction.\\n /// @param _seller The recipient of the transaction.\\n /// @return transactionID The index of the transaction.\\n function createERC20Transaction(\\n uint256 _amount,\\n IERC20 _token,\\n uint256 _deadline,\\n string memory _transactionUri,\\n address payable _seller\\n ) external returns (uint256 transactionID);\\n\\n /// @dev Pay seller. To be called if the good or service is provided.\\n /// @param _transactionID The index of the transaction.\\n /// @param _amount Amount to pay in wei.\\n function pay(uint256 _transactionID, uint256 _amount) external;\\n\\n /// @dev Reimburse buyer. To be called if the good or service can't be fully provided.\\n /// @param _transactionID The index of the transaction.\\n /// @param _amountReimbursed Amount to reimburse in wei.\\n function reimburse(uint256 _transactionID, uint256 _amountReimbursed) external;\\n\\n /// @dev Transfer the transaction's amount to the seller if the timeout has passed.\\n /// @param _transactionID The index of the transaction.\\n function executeTransaction(uint256 _transactionID) external;\\n\\n /// @dev Propose a settlement as a compromise from the initial terms to the other party.\\n /// Note that a party can only propose a settlement again after the other party has\\n /// done so as well to prevent front running/griefing issues.\\n /// @param _transactionID The index of the transaction.\\n /// @param _amount The settlement amount.\\n function proposeSettlement(uint256 _transactionID, uint256 _amount) external;\\n\\n /// @dev Accept a settlement proposed by the other party.\\n /// @param _transactionID The index of the transaction.\\n function acceptSettlement(uint256 _transactionID) external;\\n\\n /// @dev Pay the arbitration fee to raise a dispute. To be called by the buyer.\\n /// Note that it can only be called after settlement proposition.\\n /// Also note that the arbitrator can have createDispute throw, which will make\\n /// this function throw and therefore lead to a party being timed-out.\\n /// This is not a vulnerability as the arbitrator can rule in favor of one party anyway.\\n /// @param _transactionID The index of the transaction.\\n function payArbitrationFeeByBuyer(uint256 _transactionID) external payable;\\n\\n /// @dev Pay the arbitration fee to raise a dispute. To be called by the seller.\\n /// Note that this function mirrors payArbitrationFeeByBuyer.\\n /// @param _transactionID The index of the transaction.\\n function payArbitrationFeeBySeller(uint256 _transactionID) external payable;\\n\\n /// @dev Reimburse buyer if seller fails to pay the fee.\\n /// @param _transactionID The index of the transaction.\\n function timeOutByBuyer(uint256 _transactionID) external;\\n\\n /// @dev Pay seller if buyer fails to pay the fee.\\n /// @param _transactionID The index of the transaction.\\n function timeOutBySeller(uint256 _transactionID) external;\\n\\n // ************************************* //\\n // * Public Views * //\\n // ************************************* //\\n\\n /// @dev Getter to know the count of transactions.\\n /// @return The count of transactions.\\n function getTransactionCount() external view returns (uint256);\\n\\n // ************************************* //\\n // * Errors * //\\n // ************************************* //\\n\\n error GovernorOnly();\\n error BuyerOnly();\\n error SellerOnly();\\n error BuyerOrSellerOnly();\\n error ArbitratorOnly();\\n error TransactionDisputed();\\n error MaximumPaymentAmountExceeded();\\n error DeadlineNotPassed();\\n error BuyerFeeNotCoverArbitrationCosts();\\n error SellerFeeNotCoverArbitrationCosts();\\n error NotWaitingForSellerFees();\\n error NotWaitingForBuyerFees();\\n error TimeoutNotPassed();\\n error InvalidRuling();\\n error DisputeAlreadyResolved();\\n error TransactionExpired();\\n error TransactionEscalatedForArbitration();\\n error NoSettlementProposedOrTransactionMovedOnAcceptSettlement();\\n error NoSettlementProposedOrTransactionMovedOnPayFeeBuyer();\\n error NoSettlementProposedOrTransactionMovedOnPayFeeSeller();\\n error SettlementPeriodNotOver();\\n error NotSupported();\\n error TokenTransferFailed();\\n error AmountExceedsCap();\\n}\\n\",\"keccak256\":\"0x4dc29ec253ae0e2598846b4721ac03ec85c75c1f7ad8a1920290abbf411eafe2\",\"license\":\"MIT\"},\"src/interfaces/Types.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.24;\\n\\nimport {IERC20} from \\\"../libraries/SafeERC20.sol\\\";\\n\\nIERC20 constant NATIVE = IERC20(address(0));\\n\\nenum Party {\\n None,\\n Buyer, // Makes a purchase in native currency or ERC20 token.\\n Seller // Provides a good or service in exchange for native currency or ERC20 token.\\n}\\n\\nenum Status {\\n NoDispute,\\n WaitingSettlementBuyer,\\n WaitingSettlementSeller,\\n WaitingBuyer,\\n WaitingSeller,\\n DisputeCreated,\\n TransactionResolved\\n}\\n\\nenum Resolution {\\n TransactionExecuted,\\n TimeoutByBuyer,\\n TimeoutBySeller,\\n RulingEnforced,\\n SettlementReached\\n}\\n\\nstruct Transaction {\\n address payable buyer;\\n address payable seller;\\n uint256 amount;\\n uint256 settlementBuyer; // Settlement amount proposed by the buyer.\\n uint256 settlementSeller; // Settlement amount proposed by the seller.\\n uint256 deadline; // Timestamp at which the transaction can be automatically executed if not disputed.\\n uint256 disputeID; // If dispute exists, the ID of the dispute.\\n uint256 buyerFee; // Total fees paid by the buyer.\\n uint256 sellerFee; // Total fees paid by the seller.\\n uint256 lastFeePaymentTime; // Last time the dispute fees were paid by either party or settlement proposed.\\n Status status;\\n IERC20 token; // Token to pay the seller with.\\n}\\n\",\"keccak256\":\"0xa35119fdfdeb0f514e8c996d115303f916a95eff6003fdb9c1a8540f64d21ddb\",\"license\":\"MIT\"},\"src/libraries/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// Adapted from https://github.com/OpenZeppelin/openzeppelin-contracts/blob/a7a94c77463acea95d979aae1580fb0ddc3b6a1e/contracts/token/ERC20/utils/SafeERC20.sol\\n\\npragma solidity 0.8.24;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\n/// @title SafeERC20\\n/// @dev Wrappers around ERC20 operations that throw on failure (when the token\\n/// contract returns false). Tokens that return no value (and instead revert or\\n/// throw on failure) are also supported, non-reverting calls are assumed to be\\n/// successful.\\n/// To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n/// which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\nlibrary SafeERC20 {\\n /// @dev Calls transfer() without reverting.\\n /// @param _token Token to transfer.\\n /// @param _to Recepient address.\\n /// @param _value Amount transferred.\\n /// @return Whether transfer succeeded or not.\\n function safeTransfer(IERC20 _token, address _to, uint256 _value) internal returns (bool) {\\n (bool success, bytes memory data) = address(_token).call(abi.encodeCall(IERC20.transfer, (_to, _value)));\\n return (success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n\\n /// @dev Calls transferFrom() without reverting.\\n /// @param _token Token to transfer.\\n /// @param _from Sender address.\\n /// @param _to Recepient address.\\n /// @param _value Amount transferred.\\n /// @return Whether transfer succeeded or not.\\n function safeTransferFrom(IERC20 _token, address _from, address _to, uint256 _value) internal returns (bool) {\\n (bool success, bytes memory data) = address(_token).call(\\n abi.encodeCall(IERC20.transferFrom, (_from, _to, _value))\\n );\\n return (success && (data.length == 0 || abi.decode(data, (bool))));\\n }\\n}\",\"keccak256\":\"0x3a53cfe0db97fcacb3a92c085bd9d7dfe86cc3005021dfd7c372374ab13f8e84\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60a03461007257601f61107038819003918201601f19168301916001600160401b038311848410176100775780849260209460405283398101031261007257516001600160a01b0381169081900361007257608052604051610fe2908161008e8239608051818181606101526101360152f35b600080fd5b634e487b7160e01b600052604160045260246000fdfe60806040818152600436101561001457600080fd5b600091823560e01c90816366fb66751461010457508063b71dc2ba146100e3578063d65e9334146100945763e2fdcc171461004e57600080fd5b34610090578160031936011261009057517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b5080fd5b5034610090578060031936011261009057602435916001600160a01b03831683036100e057506100c96100dc92600435610afe565b9051918291602083526020830190610506565b0390f35b80fd5b5034610090576020366003190112610090576100dc906100c96004356108a8565b83833461009057602036600319011261009057634d671c6160e11b835260048035908401819052926001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811693909161018091908281602481895afa9586156104d957829683928495859261045b575b505086519163438fdfc360e11b918284528a60048501528560248501526080978885604481865afa9182156104515760249b9c8896899461042a575b5060018c519d8e88815283600482015201528a8d604481885afa95861561042057899d8a976103f0575b509060448c928e51978893849283526004830152600260248301525afa9384156103e657889a89956103ac575b50501690816102fe57505050509361029d61025489956102c5956102a29561027d61025e6102596102b79f6100dc9e9d61024a610254926108a8565b9560011c9061072a565b6108a8565b6105ba565b9c8a81146102e7576102786102728461065b565b916108a8565b61069e565b98610288848861072a565b146102d257610297915061065b565b9361072a565b61074d565b915b8351968796606088526060880190610506565b908682036020880152610506565b9184830390850152610506565b508851906102df8261052b565b81529361072a565b6102788c516102f58161052b565b858152916108a8565b899897999550819396919294508b83916103188383610afe565b9261032291610afe565b61032b906105ba565b9b14156000149b61036b6100dc9b6103656102b79f9a61037a9a61029d996102c59d61039557610278915061035f8861065b565b92610afe565b9a61072a565b146103805761035f915061065b565b916102a4565b5087519061038d8261052b565b815292610afe565b61027891516103a38161052b565b89815292610afe565b6103d1939b508091929550903d106103df575b6103c9818361055d565b810190610598565b9a9250905098928d8061020e565b503d6103bf565b8b513d8a823e3d90fd5b8c92919e508d9750610410604491843d86116103df576103c9818361055d565b925090509f9098509192506101e1565b8c513d8b823e3d90fd5b9093506104459196508a3d8c116103df576103c9818361055d565b5050959095928e6101b7565b8a513d89823e3d90fd5b9350945050955082813d83116104d2575b610476818361055d565b810103126100e0576104878261057f565b506104946020830161057f565b50838201519160e08101519561010082015191600761014082015110156104ce5761016001519385851685036104ce57969193898061017b565b8380fd5b503d61046c565b85513d84823e3d90fd5b60005b8381106104f65750506000910152565b81810151838201526020016104e6565b9060209161051f815180928185528580860191016104e3565b601f01601f1916010190565b6020810190811067ffffffffffffffff82111761054757604052565b634e487b7160e01b600052604160045260246000fd5b90601f8019910116810190811067ffffffffffffffff82111761054757604052565b51906001600160a01b038216820361059357565b600080fd5b9190826080910312610593578151916020810151916060604083015192015190565b9061063d605c6040518094740213abcb2b91030b7321029b2b63632b91033b2ba1605d1b60208301526105f78151809260206035860191016104e3565b81017f206261636b20616e642068616c66206f6620746865206172626974726174696f60358201526637103332b2b99760c91b605582015203603c81018552018361055d565b565b67ffffffffffffffff811161054757601f01601f191660200190565b9061063d602c60405180946b01034b739ba32b0b21037b3160a51b602083015261068e81518092602086860191016104e3565b810103600c81018552018361055d565b604c61063d919392936040519485916a0213abcb2b9103830bcb9960ad1b60208401526106d5815180926020602b870191016104e3565b82016106eb825180936020602b850191016104e3565b017f2c206765747320746865206172626974726174696f6e2066656573206261636b602b820152601760f91b604b82015203602c81018552018361055d565b9190820391821161073757565b634e487b7160e01b600052601160045260246000fd5b605361063d919392936040519485916a0213abcb2b9103830bcb9960ad1b6020840152610784815180926020602b870191016104e3565b820161079a825180936020602b850191016104e3565b017f2c2053656c6c6572206765747320746865206172626974726174696f6e206665602b8201526732b9903130b1b59760c11b604b82015203603381018552018361055d565b81156107ea570490565b634e487b7160e01b600052601260045260246000fd5b81156107ea570690565b9061063d60216040518094600360fc1b602083015261083281518092602086860191016104e3565b810103600181018552018361055d565b908151811015610853570160200190565b634e487b7160e01b600052603260045260246000fd5b8015610737576000190190565b906108808261063f565b61088d604051918261055d565b828152809261089e601f199161063f565b0190602036910137565b6108c7670de0b6b3a764000066038d7ea4c68000818406049204610e48565b908015610a04576108d790610e48565b6003815110156108ef576108ea9061080a565b6108d7565b80515b801515806109c0575b1561090e5761090990610869565b6108f2565b9091908061091c5750905090565b61092581610876565b9260009060005b838110610995575050505060256109929160405193816109568693518092602080870191016104e3565b8201601760f91b60208201526109768251809360206021850191016104e3565b01630408aa8960e31b602182015203600581018452018261055d565b90565b6001906001600160f81b03196109ab8285610842565b5116841a6109b98289610842565b530161092c565b5060001981018181116109ef57600360fc1b906001600160f81b0319906109e79085610842565b5116146108fb565b60246000634e487b7160e01b81526011600452fd5b50610992602460405183610a228295518092602080860191016104e3565b8101630408aa8960e31b602082015203600481018452018261055d565b8015610aa857600190602081108216604e8210831617610aa0578190600a925b808211610a7757505081600019048111610737570290565b90928060001904811161073757818416610a97575b800292811c90610a5f565b80920291610a8c565b9050600a0a90565b50600190565b602161063d919392936040519481610ad08793518092602080870191016104e3565b8201600160fd1b6020820152610aef82518093602087850191016104e3565b0103600181018552018361055d565b916001600160a01b03909116908115610e0b576040805163313ce56760e01b81526004939160209081838781875afa928315610dc357600093610dce575b5060006004948251958680926395d89b4160e01b82525afa938415610dc357600094610d46575b5060ff9660ff841690610b7582610a3f565b91610b8083836107e0565b9560038210610d2f57506002190160ff811161073757610bb492610ba960ff610baf9316610a3f565b92610800565b6107e0565b92610bc0600391610e48565b938015610d1d57610bd090610e48565b80518983161115610be957610be49061080a565b610bd0565b97505086515b80151580610cd9575b15610c0b57610c0690610869565b610bef565b92939495508215600014610c2757505050610992929350610aae565b610c32839593610876565b9460005b818110610cad5750506109929495965090610c9e6022949392519684610c65899651809286808a0191016104e3565b8501601760f91b84820152610c8382518093866021850191016104e3565b0191600160fd1b6021840152835193849187850191016104e3565b0103600281018452018261055d565b6001906001600160f81b0319610cc3828c610842565b511660001a610cd2828a610842565b5301610c36565b506000198101818111610d0857600360fc1b906001600160f81b031990610d00908b610842565b511614610bf8565b601188634e487b7160e01b6000525260246000fd5b50505050909193506109929250610aae565b9592610d3f9150610bc092610800565b9491610e48565b90933d8082843e610d57818461055d565b82019183818403126100905780519067ffffffffffffffff8211610dbf570182601f8201121561009057805191610d8d8361063f565b93610d9a8851958661055d565b8385528584840101116100e0575090610db8918480850191016104e3565b9238610b63565b8280fd5b50513d6000823e3d90fd5b8281819593943d8311610e04575b610de6818361055d565b8101031261009057519060ff821682036100e0575091906000610b3c565b503d610ddc565b60405162461bcd60e51b8152602060048201526015602482015274496e76616c696420746f6b656e206164647265737360581b6044820152606490fd5b6000908072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b80821015610f9e575b506d04ee2d6d415b85acef810000000080831015610f8f575b50662386f26fc1000080831015610f80575b506305f5e10080831015610f71575b5061271080831015610f62575b506064821015610f52575b600a80921015610f48575b6001908160216001860195610edd8761063f565b96610eeb604051988961055d565b808852610efa601f199161063f565b01366020890137860101905b610f12575b5050505090565b600019019083906f181899199a1a9b1b9c1cb0b131b232b360811b8282061a835304918215610f4357919082610f06565b610f0b565b9160010191610ec9565b9190606460029104910191610ebe565b60049193920491019138610eb3565b60089193920491019138610ea6565b60109193920491019138610e97565b60209193920491019138610e85565b604093508104915038610e6c56fea264697066735822122073a17dbf5f889088f7d774070628b8669eb533de4334b942ad062e2ad7f6f9f564736f6c63430008180033", + "deployedBytecode": "0x60806040818152600436101561001457600080fd5b600091823560e01c90816366fb66751461010457508063b71dc2ba146100e3578063d65e9334146100945763e2fdcc171461004e57600080fd5b34610090578160031936011261009057517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b5080fd5b5034610090578060031936011261009057602435916001600160a01b03831683036100e057506100c96100dc92600435610afe565b9051918291602083526020830190610506565b0390f35b80fd5b5034610090576020366003190112610090576100dc906100c96004356108a8565b83833461009057602036600319011261009057634d671c6160e11b835260048035908401819052926001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811693909161018091908281602481895afa9586156104d957829683928495859261045b575b505086519163438fdfc360e11b918284528a60048501528560248501526080978885604481865afa9182156104515760249b9c8896899461042a575b5060018c519d8e88815283600482015201528a8d604481885afa95861561042057899d8a976103f0575b509060448c928e51978893849283526004830152600260248301525afa9384156103e657889a89956103ac575b50501690816102fe57505050509361029d61025489956102c5956102a29561027d61025e6102596102b79f6100dc9e9d61024a610254926108a8565b9560011c9061072a565b6108a8565b6105ba565b9c8a81146102e7576102786102728461065b565b916108a8565b61069e565b98610288848861072a565b146102d257610297915061065b565b9361072a565b61074d565b915b8351968796606088526060880190610506565b908682036020880152610506565b9184830390850152610506565b508851906102df8261052b565b81529361072a565b6102788c516102f58161052b565b858152916108a8565b899897999550819396919294508b83916103188383610afe565b9261032291610afe565b61032b906105ba565b9b14156000149b61036b6100dc9b6103656102b79f9a61037a9a61029d996102c59d61039557610278915061035f8861065b565b92610afe565b9a61072a565b146103805761035f915061065b565b916102a4565b5087519061038d8261052b565b815292610afe565b61027891516103a38161052b565b89815292610afe565b6103d1939b508091929550903d106103df575b6103c9818361055d565b810190610598565b9a9250905098928d8061020e565b503d6103bf565b8b513d8a823e3d90fd5b8c92919e508d9750610410604491843d86116103df576103c9818361055d565b925090509f9098509192506101e1565b8c513d8b823e3d90fd5b9093506104459196508a3d8c116103df576103c9818361055d565b5050959095928e6101b7565b8a513d89823e3d90fd5b9350945050955082813d83116104d2575b610476818361055d565b810103126100e0576104878261057f565b506104946020830161057f565b50838201519160e08101519561010082015191600761014082015110156104ce5761016001519385851685036104ce57969193898061017b565b8380fd5b503d61046c565b85513d84823e3d90fd5b60005b8381106104f65750506000910152565b81810151838201526020016104e6565b9060209161051f815180928185528580860191016104e3565b601f01601f1916010190565b6020810190811067ffffffffffffffff82111761054757604052565b634e487b7160e01b600052604160045260246000fd5b90601f8019910116810190811067ffffffffffffffff82111761054757604052565b51906001600160a01b038216820361059357565b600080fd5b9190826080910312610593578151916020810151916060604083015192015190565b9061063d605c6040518094740213abcb2b91030b7321029b2b63632b91033b2ba1605d1b60208301526105f78151809260206035860191016104e3565b81017f206261636b20616e642068616c66206f6620746865206172626974726174696f60358201526637103332b2b99760c91b605582015203603c81018552018361055d565b565b67ffffffffffffffff811161054757601f01601f191660200190565b9061063d602c60405180946b01034b739ba32b0b21037b3160a51b602083015261068e81518092602086860191016104e3565b810103600c81018552018361055d565b604c61063d919392936040519485916a0213abcb2b9103830bcb9960ad1b60208401526106d5815180926020602b870191016104e3565b82016106eb825180936020602b850191016104e3565b017f2c206765747320746865206172626974726174696f6e2066656573206261636b602b820152601760f91b604b82015203602c81018552018361055d565b9190820391821161073757565b634e487b7160e01b600052601160045260246000fd5b605361063d919392936040519485916a0213abcb2b9103830bcb9960ad1b6020840152610784815180926020602b870191016104e3565b820161079a825180936020602b850191016104e3565b017f2c2053656c6c6572206765747320746865206172626974726174696f6e206665602b8201526732b9903130b1b59760c11b604b82015203603381018552018361055d565b81156107ea570490565b634e487b7160e01b600052601260045260246000fd5b81156107ea570690565b9061063d60216040518094600360fc1b602083015261083281518092602086860191016104e3565b810103600181018552018361055d565b908151811015610853570160200190565b634e487b7160e01b600052603260045260246000fd5b8015610737576000190190565b906108808261063f565b61088d604051918261055d565b828152809261089e601f199161063f565b0190602036910137565b6108c7670de0b6b3a764000066038d7ea4c68000818406049204610e48565b908015610a04576108d790610e48565b6003815110156108ef576108ea9061080a565b6108d7565b80515b801515806109c0575b1561090e5761090990610869565b6108f2565b9091908061091c5750905090565b61092581610876565b9260009060005b838110610995575050505060256109929160405193816109568693518092602080870191016104e3565b8201601760f91b60208201526109768251809360206021850191016104e3565b01630408aa8960e31b602182015203600581018452018261055d565b90565b6001906001600160f81b03196109ab8285610842565b5116841a6109b98289610842565b530161092c565b5060001981018181116109ef57600360fc1b906001600160f81b0319906109e79085610842565b5116146108fb565b60246000634e487b7160e01b81526011600452fd5b50610992602460405183610a228295518092602080860191016104e3565b8101630408aa8960e31b602082015203600481018452018261055d565b8015610aa857600190602081108216604e8210831617610aa0578190600a925b808211610a7757505081600019048111610737570290565b90928060001904811161073757818416610a97575b800292811c90610a5f565b80920291610a8c565b9050600a0a90565b50600190565b602161063d919392936040519481610ad08793518092602080870191016104e3565b8201600160fd1b6020820152610aef82518093602087850191016104e3565b0103600181018552018361055d565b916001600160a01b03909116908115610e0b576040805163313ce56760e01b81526004939160209081838781875afa928315610dc357600093610dce575b5060006004948251958680926395d89b4160e01b82525afa938415610dc357600094610d46575b5060ff9660ff841690610b7582610a3f565b91610b8083836107e0565b9560038210610d2f57506002190160ff811161073757610bb492610ba960ff610baf9316610a3f565b92610800565b6107e0565b92610bc0600391610e48565b938015610d1d57610bd090610e48565b80518983161115610be957610be49061080a565b610bd0565b97505086515b80151580610cd9575b15610c0b57610c0690610869565b610bef565b92939495508215600014610c2757505050610992929350610aae565b610c32839593610876565b9460005b818110610cad5750506109929495965090610c9e6022949392519684610c65899651809286808a0191016104e3565b8501601760f91b84820152610c8382518093866021850191016104e3565b0191600160fd1b6021840152835193849187850191016104e3565b0103600281018452018261055d565b6001906001600160f81b0319610cc3828c610842565b511660001a610cd2828a610842565b5301610c36565b506000198101818111610d0857600360fc1b906001600160f81b031990610d00908b610842565b511614610bf8565b601188634e487b7160e01b6000525260246000fd5b50505050909193506109929250610aae565b9592610d3f9150610bc092610800565b9491610e48565b90933d8082843e610d57818461055d565b82019183818403126100905780519067ffffffffffffffff8211610dbf570182601f8201121561009057805191610d8d8361063f565b93610d9a8851958661055d565b8385528584840101116100e0575090610db8918480850191016104e3565b9238610b63565b8280fd5b50513d6000823e3d90fd5b8281819593943d8311610e04575b610de6818361055d565b8101031261009057519060ff821682036100e0575091906000610b3c565b503d610ddc565b60405162461bcd60e51b8152602060048201526015602482015274496e76616c696420746f6b656e206164647265737360581b6044820152606490fd5b6000908072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b80821015610f9e575b506d04ee2d6d415b85acef810000000080831015610f8f575b50662386f26fc1000080831015610f80575b506305f5e10080831015610f71575b5061271080831015610f62575b506064821015610f52575b600a80921015610f48575b6001908160216001860195610edd8761063f565b96610eeb604051988961055d565b808852610efa601f199161063f565b01366020890137860101905b610f12575b5050505090565b600019019083906f181899199a1a9b1b9c1cb0b131b232b360811b8282061a835304918215610f4357919082610f06565b610f0b565b9160010191610ec9565b9190606460029104910191610ebe565b60049193920491019138610eb3565b60089193920491019138610ea6565b60109193920491019138610e97565b60209193920491019138610e85565b604093508104915038610e6c56fea264697066735822122073a17dbf5f889088f7d774070628b8669eb533de4334b942ad062e2ad7f6f9f564736f6c63430008180033", + "devdoc": { + "kind": "dev", + "methods": { + "constructor": { + "params": { + "_escrow": "The address of the EscrowUniversal contract." + } + }, + "formatEth(uint256)": { + "params": { + "_amountWei": "The amount in wei." + }, + "returns": { + "_0": "The formatted amount." + } + }, + "formatToken(uint256,address)": { + "params": { + "_amountWei": "The amount in wei.", + "_token": "The address of the token." + }, + "returns": { + "_0": "The formatted amount." + } + }, + "getPayoutMessages(uint256)": { + "returns": { + "buyerWins": "The payout message for the case where the buyer wins.", + "noWinner": "The payout message for the case where nobody wins.", + "sellerWins": "The payout message for the case where the seller wins." + } + } + }, + "title": "EscrowView", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "constructor": { + "notice": "Initialize the view contract with the address of the EscrowUniversal contract." + }, + "formatEth(uint256)": { + "notice": "Format an amount in ETH to 3 decimal places." + }, + "formatToken(uint256,address)": { + "notice": "Format an amount in a token to 3 decimal places." + }, + "getPayoutMessages(uint256)": { + "notice": "Get the payout messages for a transaction *once* a dispute is created.The amounts are exclusive of arbitration fees for clarity.The amounts pre-dispute are imprecise as the arbitration fees are not paid yet by either or both parties." + } + }, + "notice": "A view contract for EscrowUniversal to facilitate the display of ruling options.", + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file diff --git a/contracts/scripts/setDisputeTemplate.ts b/contracts/scripts/setDisputeTemplate.ts index 956de77..5c0dcc9 100644 --- a/contracts/scripts/setDisputeTemplate.ts +++ b/contracts/scripts/setDisputeTemplate.ts @@ -1,6 +1,7 @@ // import { BigNumber, utils } from "ethers"; import { task } from "hardhat/config"; import { getContracts } from "../deploy/utils/getContracts"; +import { EscrowCustomBuyer, EscrowUniversal, EscrowView } from "../typechain-types"; const parameters = { arbitrumSepoliaDevnet: { @@ -96,7 +97,13 @@ const mappingFn = (subgraphEndpoint: string, view: string) => `[ task("set-dispute-template", "Sets the dispute template").setAction(async (args, hre) => { const { config, deployments } = hre; - const { escrow, view, klerosCore } = await getContracts(hre); + const { + escrow: escrowUniversal, + view: viewUniversal, + escrowCustomBuyer, + customBuyerView, + klerosCore, + } = await getContracts(hre); const networkName = await deployments.getNetworkName(); const { subgraphEndpoint, frontendUrl } = parameters[networkName]; const chainId = config.networks[networkName].chainId; @@ -105,14 +112,22 @@ task("set-dispute-template", "Sets the dispute template").setAction(async (args, throw new Error("Missing parameters"); } - const disputeTemplate = disputeTemplateFn(chainId, klerosCore.target.toString(), frontendUrl); - console.log("New disputeTemplate", disputeTemplate); + const setDisputeTemplate = async (escrow: EscrowUniversal | EscrowCustomBuyer, view: EscrowView) => { + const disputeTemplate = disputeTemplateFn(chainId, klerosCore.target.toString(), frontendUrl); + console.log("New disputeTemplate", disputeTemplate); - const mapping = mappingFn(subgraphEndpoint, view.target.toString()); - console.log("New mapping", mapping); + const mapping = mappingFn(subgraphEndpoint, view.target.toString()); + console.log("New mapping", mapping); - const tx = await escrow.changeDisputeTemplate(disputeTemplate, mapping); - await tx.wait().then((receipt) => { - console.log(`Transaction receipt: ${JSON.stringify(receipt)}`); - }); + const tx = await escrow.changeDisputeTemplate(disputeTemplate, mapping); + await tx.wait().then((receipt) => { + console.log(`Transaction receipt: ${JSON.stringify(receipt)}`); + }); + }; + + await setDisputeTemplate(escrowUniversal, viewUniversal); + + if (escrowCustomBuyer) { + await setDisputeTemplate(escrowCustomBuyer, customBuyerView); + } }); diff --git a/contracts/src/EscrowCustomBuyer.sol b/contracts/src/EscrowCustomBuyer.sol index 210327a..84a6568 100644 --- a/contracts/src/EscrowCustomBuyer.sol +++ b/contracts/src/EscrowCustomBuyer.sol @@ -7,7 +7,7 @@ pragma solidity 0.8.24; -import "./EscrowUniversal.sol"; +import {EscrowUniversal, SafeERC20, IERC20, IArbitratorV2, IDisputeTemplateRegistry, NATIVE, Transaction} from "./EscrowUniversal.sol"; /// @title EscrowCustomBuyer. /// @dev Version of Escrow that allows to specify a buyer when transaction is created. @@ -30,15 +30,17 @@ contract EscrowCustomBuyer is EscrowUniversal { IDisputeTemplateRegistry _templateRegistry, uint256 _feeTimeout, uint256 _settlementTimeout - ) EscrowUniversal( - _arbitrator, - _arbitratorExtraData, - _templateData, - _templateDataMappings, - _templateRegistry, - _feeTimeout, - _settlementTimeout - ) {} + ) + EscrowUniversal( + _arbitrator, + _arbitratorExtraData, + _templateData, + _templateDataMappings, + _templateRegistry, + _feeTimeout, + _settlementTimeout + ) + {} /// @dev Create a native transaction with custom buyer. /// @param _deadline Time after which a party can automatically execute the arbitrable transaction. @@ -62,16 +64,9 @@ contract EscrowCustomBuyer is EscrowUniversal { transactionID = transactions.length - 1; - emit NativeTransactionCreated( - transactionID, - _transactionUri, - _buyer, - _seller, - msg.value, - transaction.deadline - ); + emit NativeTransactionCreated(transactionID, _transactionUri, _buyer, _seller, msg.value, transaction.deadline); } - + /// @dev Create an ERC20 transaction with custom buyer address. /// @param _amount The amount of tokens in this transaction. /// @param _token The ERC20 token contract.