diff --git a/hardhat.config.js b/hardhat.config.js index ff165e2e6..439e04682 100644 --- a/hardhat.config.js +++ b/hardhat.config.js @@ -115,6 +115,15 @@ module.exports = { }, }, }, + { + version: '0.8.23', + settings: { + optimizer: { + enabled: true, + runs: 999999, + }, + }, + }, ], }, etherscan: { diff --git a/source/balances/deploys.js b/source/balances/deploys.js deleted file mode 100644 index f8c2a4558..000000000 --- a/source/balances/deploys.js +++ /dev/null @@ -1,18 +0,0 @@ -module.exports = { - 1: '0x21486E4427031F10fBE45F47AAd6f729014d42a4', - 4: '0x2B1c6b0cB9673Efc83d177f72c0daF52A33F120C', - 5: '0x755Aa03f420A62560E90502D7da23A73C301dad4', - 30: '0xEAa610106E67Fe191b0f33cF9B8C900Fed1Ba4BA', - 31: '0x9e9c21C4747B078712D2bb49A279A043973BE9a0', - 40: '0xc17720af2950Ab4af32363789e437eCEA5D2425C', - 41: '0xA4fD7555766ebE1Eb284879Cb75f3d5dae719aD6', - 42: '0xe25b7504856bfb230b7c32BC87047479815cbc70', - 56: '0x4f850F83BB5678E1deBA0B8F4bcBA9813Ef08dCa', - 97: '0x4f850F83BB5678E1deBA0B8F4bcBA9813Ef08dCa', - 137: '0x132F13C3896eAB218762B9e46F55C9c478905849', - 43113: '0x87D02f7C95b6bC3C9220Fd8fBE1042aCAd590102', - 43114: '0x8fd3121013A07C57f0D69646E86E7a4880b467b7', - 59140: '0x51F372bE64F0612532F28142cECF8F204B272622', - 59144: '0xDECA72bDA0cDf62d79b46B1585B380c9C6d57D9E', - 80001: '0x132F13C3896eAB218762B9e46F55C9c478905849', -} diff --git a/source/balances/deploys.js.d.ts b/source/balances/deploys.js.d.ts deleted file mode 100644 index 58ac83ce2..000000000 --- a/source/balances/deploys.js.d.ts +++ /dev/null @@ -1 +0,0 @@ -declare module '@airswap/balances/deploys.js' diff --git a/source/balances/README.md b/source/batch-call/README.md similarity index 81% rename from source/balances/README.md rename to source/batch-call/README.md index 2b03417b0..6e258a633 100644 --- a/source/balances/README.md +++ b/source/batch-call/README.md @@ -1,4 +1,4 @@ -# BalanceChecker +# BatchCall [AirSwap](https://www.airswap.io/) is a peer-to-peer trading network for Ethereum tokens. This package contains source code and tests for a basic ERC20 balance and allowance aggregator. @@ -15,7 +15,7 @@ ## Usage -:warning: This package is under active development. The [BalanceChecker](./contracts/BalanceChecker.sol) contract is deployed; see [deploys.js](./deploys.js) for latest. For all AirSwap contract deployments see [Deployed Contracts](https://docs.airswap.io/system/contract-deployments). +:warning: This package is under active development. The [BatchCall](./contracts/BatchCall.sol) contract is deployed; see [deploys.js](./deploys.js) for latest. For all AirSwap contract deployments see [Deployed Contracts](https://docs.airswap.io/system/contract-deployments). ## Commands diff --git a/source/balances/contracts/BalanceChecker.sol b/source/batch-call/contracts/BatchCall.sol similarity index 77% rename from source/balances/contracts/BalanceChecker.sol rename to source/batch-call/contracts/BatchCall.sol index 10bde221d..0a3268a1a 100644 --- a/source/balances/contracts/BalanceChecker.sol +++ b/source/batch-call/contracts/BatchCall.sol @@ -1,15 +1,16 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.17; +pragma solidity 0.8.23; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "@openzeppelin/contracts/utils/Address.sol"; +import "@airswap/swap/contracts/interfaces/ISwap.sol"; +import "@airswap/swap-erc20/contracts/interfaces/ISwapERC20.sol"; /** - * @title BalanceChecker: Batch ERC-20 allowance and balance calls + * @title BatchCalling: Batch balance, allowance, order validity checks */ -contract BalanceChecker is Ownable { +contract BatchCall { using SafeERC20 for IERC20; using Address for address; @@ -127,36 +128,6 @@ contract BalanceChecker is Ownable { return balances; } - /** - * @notice Self-destruct contract for clean-up - */ - function destruct(address payable recipientAddress) public onlyOwner { - selfdestruct(recipientAddress); - } - - /** - * @notice Allow owner to withdraw ether from contract - */ - function withdraw() public onlyOwner { - (bool success, ) = address(owner()).call{ value: address(this).balance }( - "" - ); - require(success, "ETH_WITHDRAW_FAILED"); - } - - /** - * @notice Allow owner to withdraw stuck tokens from contract - * @param tokenAddress address - * @param amount uint256 - */ - function withdrawToken( - address tokenAddress, - uint256 amount - ) public onlyOwner { - require(tokenAddress != address(0x0)); //use withdraw for ETH - IERC20(tokenAddress).safeTransfer(msg.sender, amount); - } - /** * @notice Check the token allowance of a wallet in a token contract * @dev return 0 on returns 0 on invalid spender contract or non-contract address @@ -212,4 +183,55 @@ contract BalanceChecker is Ownable { } return 0; } + + /** + * @notice Check if the validity of an array of Orders + * @dev return array and will fail if large token arrays are inputted + * @dev Returns an array of bool + * @param orders[] list of orders to be checked + * @return bool[] order validity + */ + + function checkOrders( + address senderWallet, + ISwap.Order[] calldata orders, + ISwap swapContract + ) external view returns (bool[] memory) { + require(orders.length > 0); + bool[] memory orderValidity = new bool[](orders.length); + + for (uint256 i = 0; i < orders.length; i++) { + (, uint256 errorCount) = swapContract.check(senderWallet, orders[i]); + orderValidity[i] = errorCount == 0 ? true : false; + } + return orderValidity; + } + + function checkOrdersERC20( + address senderWallet, + ISwapERC20.OrderERC20[] calldata ordersERC20, + ISwapERC20 swapERC20Contract + ) external view returns (bool[] memory) { + require(ordersERC20.length > 0); + bool[] memory orderValidity = new bool[](ordersERC20.length); + + for (uint256 i = 0; i < ordersERC20.length; i++) { + ISwapERC20.OrderERC20 memory order = ordersERC20[i]; + (uint256 errorCount, ) = swapERC20Contract.check( + senderWallet, + order.nonce, + order.expiry, + order.signerWallet, + order.signerToken, + order.signerAmount, + order.senderToken, + order.senderAmount, + order.v, + order.r, + order.s + ); + orderValidity[i] = errorCount == 0 ? true : false; + } + return orderValidity; + } } diff --git a/source/batch-call/deploys-blocks.js b/source/batch-call/deploys-blocks.js new file mode 100644 index 000000000..5fcd90cd8 --- /dev/null +++ b/source/batch-call/deploys-blocks.js @@ -0,0 +1,4 @@ +module.exports = { + 5: 10351183, + 11155111: 5059276, +} diff --git a/source/batch-call/deploys-blocks.js.d.ts b/source/batch-call/deploys-blocks.js.d.ts new file mode 100644 index 000000000..c2b754c48 --- /dev/null +++ b/source/batch-call/deploys-blocks.js.d.ts @@ -0,0 +1 @@ +declare module '@airswap/batch-call/deploys-blocks.js' diff --git a/source/batch-call/deploys.js b/source/batch-call/deploys.js new file mode 100644 index 000000000..f94c303ea --- /dev/null +++ b/source/batch-call/deploys.js @@ -0,0 +1,4 @@ +module.exports = { + 5: '0x1104d8e1f4499acbabbcd55c9a6c957e1f881318', + 11155111: '0x1104D8E1F4499ACbaBBcD55c9A6C957E1F881318', +} diff --git a/source/batch-call/deploys.js.d.ts b/source/batch-call/deploys.js.d.ts new file mode 100644 index 000000000..ca312d63e --- /dev/null +++ b/source/batch-call/deploys.js.d.ts @@ -0,0 +1 @@ +declare module '@airswap/batch-call/deploys.js' diff --git a/source/balances/hardhat.config.js b/source/batch-call/hardhat.config.js similarity index 100% rename from source/balances/hardhat.config.js rename to source/batch-call/hardhat.config.js diff --git a/source/balances/package.json b/source/batch-call/package.json similarity index 73% rename from source/balances/package.json rename to source/batch-call/package.json index 223235d27..7baa7c10a 100644 --- a/source/balances/package.json +++ b/source/batch-call/package.json @@ -1,7 +1,7 @@ { - "name": "@airswap/balances", - "version": "4.0.4", - "description": "Batch balance and allowance calls", + "name": "@airswap/batch-call", + "version": "4.1.0-beta.0", + "description": "Batch balance, allowance, order validity checks", "license": "MIT", "repository": { "type": "git", @@ -26,10 +26,12 @@ "owners": "hardhat run ./scripts/owner.js" }, "dependencies": { - "@openzeppelin/contracts": "^4.8.3" + "@openzeppelin/contracts": "^4.8.3", + "@airswap/swap": "4.1.3-beta.0", + "@airswap/swap-erc20": "4.1.7-beta.0" }, "devDependencies": { - "@airswap/constants": "4.1.8", + "@airswap/constants": "4.1.9-beta.0", "@airswap/utils": "4.1.12", "prompt-confirm": "^2.0.4" }, diff --git a/source/balances/scripts/deploy.js b/source/batch-call/scripts/deploy.js similarity index 51% rename from source/balances/scripts/deploy.js rename to source/batch-call/scripts/deploy.js index 2fe077159..9539ac414 100644 --- a/source/balances/scripts/deploy.js +++ b/source/batch-call/scripts/deploy.js @@ -1,10 +1,12 @@ /* eslint-disable no-console */ const fs = require('fs') +const prettier = require('prettier') const Confirm = require('prompt-confirm') const { ethers, run } = require('hardhat') const { ChainIds, chainNames, chainLabels } = require('@airswap/constants') const { getReceiptUrl } = require('@airswap/utils') -const balancesDeploys = require('../deploys.js') +const batchCallDeploys = require('../deploys.js') +const batchCallBlocks = require('../deploys-blocks.js') async function main() { await run('compile') @@ -21,23 +23,36 @@ async function main() { const prompt = new Confirm('Proceed to deploy?') if (await prompt.run()) { - const balanceCheckerFactory = await ethers.getContractFactory( - 'BalanceChecker' - ) - const balanceCheckerContract = await balanceCheckerFactory.deploy() + const prettierConfig = await prettier.resolveConfig('../deploys.js') + const batchFactory = await ethers.getContractFactory('BatchCall') + const batchCallContract = await batchFactory.deploy() console.log( 'Deploying...', - getReceiptUrl(chainId, balanceCheckerContract.deployTransaction.hash) + getReceiptUrl(chainId, batchCallContract.deployTransaction.hash) ) - await balanceCheckerContract.deployed() - console.log(`Deployed: ${balanceCheckerContract.address}`) + await batchCallContract.deployed() - balancesDeploys[chainId] = balanceCheckerContract.address + batchCallDeploys[chainId] = batchCallContract.address fs.writeFileSync( './deploys.js', - `module.exports = ${JSON.stringify(balancesDeploys, null, '\t')}` + prettier.format( + `module.exports = ${JSON.stringify(batchCallDeploys, null, '\t')}`, + { ...prettierConfig, parser: 'babel' } + ) + ) + batchCallBlocks[chainId] = ( + await batchCallContract.deployTransaction.wait() + ).blockNumber + fs.writeFileSync( + './deploys-blocks.js', + prettier.format( + `module.exports = ${JSON.stringify(batchCallBlocks, null, '\t')}`, + { ...prettierConfig, parser: 'babel' } + ) + ) + console.log( + `Deployed: ${batchCallDeploys[chainId]} @ ${batchCallBlocks[chainId]}` ) - console.log('Updated deploys.js') console.log( `\nVerify with "yarn verify --network ${chainLabels[ diff --git a/source/balances/scripts/owner.js b/source/batch-call/scripts/owner.js similarity index 100% rename from source/balances/scripts/owner.js rename to source/batch-call/scripts/owner.js diff --git a/source/balances/scripts/verify.js b/source/batch-call/scripts/verify.js similarity index 86% rename from source/balances/scripts/verify.js rename to source/batch-call/scripts/verify.js index 6ef2f543c..6d0e4679c 100644 --- a/source/balances/scripts/verify.js +++ b/source/batch-call/scripts/verify.js @@ -1,7 +1,7 @@ /* eslint-disable no-console */ const { ethers, run } = require('hardhat') const { chainNames } = require('@airswap/constants') -const balancesDeploys = require('../deploys.js') +const batchCallDeploys = require('../deploys.js') async function main() { await run('compile') @@ -12,7 +12,7 @@ async function main() { console.log(`Verifying on ${chainNames[chainId].toUpperCase()}`) await run('verify:verify', { - address: balancesDeploys[chainId], + address: batchCallDeploys[chainId], constructorArguments: [], }) } diff --git a/source/batch-call/test/BatchCall.js b/source/batch-call/test/BatchCall.js new file mode 100644 index 000000000..2ddbad0ff --- /dev/null +++ b/source/batch-call/test/BatchCall.js @@ -0,0 +1,232 @@ +const { expect } = require('chai') +const { ethers, waffle } = require('hardhat') +const { deployMockContract } = waffle +const IERC20 = require('@openzeppelin/contracts/build/contracts/IERC20.json') +const IERC721 = require('@openzeppelin/contracts/build/contracts/ERC721Royalty.json') +const SWAP = require('@airswap/swap/build/contracts/Swap.sol/Swap.json') +const SWAP_ERC20 = require('@airswap/swap-erc20/build/contracts/SwapERC20.sol/SwapERC20.json') +const ERC20_ADAPTER = require('@airswap/swap/build/contracts/adapters/ERC20Adapter.sol/ERC20Adapter.json') +const ERC721_ADAPTER = require('@airswap/swap/build/contracts/adapters/ERC721Adapter.sol/ERC721Adapter.json') +const { + createOrder, + createOrderSignature, + createOrderERC20, + createOrderERC20Signature, +} = require('@airswap/utils') +const { TokenKinds } = require('@airswap/constants') + +const CHAIN_ID = 31337 +const PROTOCOL_FEE = '30' +const PROTOCOL_FEE_LIGHT = '7' +const DEFAULT_AMOUNT = '1000' +const DEFAULT_BALANCE = '100000' +const BONUS_SCALE = '10' +const BONUS_MAX = '100' + +let snapshotId +let deployer +let signer +let sender +let erc20token +let erc20adapter +let erc721token +let erc721adapter +let swap +let swapERC20 +let batchCall + +async function signOrder(order, wallet, swapContract) { + return { + ...order, + ...(await createOrderSignature(order, wallet, swapContract, CHAIN_ID)), + } +} + +async function createSignedOrder(params, signatory) { + const unsignedOrder = createOrder({ + protocolFee: PROTOCOL_FEE, + ...params, + signer: { + wallet: signer.address, + token: erc20token.address, + kind: TokenKinds.ERC20, + id: '0', + amount: DEFAULT_AMOUNT, + ...params.signer, + }, + sender: { + wallet: sender.address, + token: erc20token.address, + kind: TokenKinds.ERC20, + id: '0', + amount: DEFAULT_AMOUNT, + ...params.sender, + }, + }) + return await signOrder(unsignedOrder, signatory, swap.address, CHAIN_ID) +} + +async function createSignedOrderERC20(params, signatory) { + const unsignedOrder = createOrderERC20({ + protocolFee: PROTOCOL_FEE, + signerWallet: signer.address, + signerToken: erc20token.address, + signerAmount: DEFAULT_AMOUNT, + senderWallet: sender.address, + senderToken: erc20token.address, + senderAmount: DEFAULT_AMOUNT, + ...params, + }) + return { + ...unsignedOrder, + ...(await createOrderERC20Signature( + unsignedOrder, + signatory, + swapERC20.address, + CHAIN_ID + )), + } +} + +async function setUpAllowances(senderAmount, signerAmount) { + await erc20token.mock.allowance + .withArgs(sender.address, swap.address) + .returns(senderAmount) + await erc20token.mock.allowance + .withArgs(signer.address, swap.address) + .returns(signerAmount) + + await erc20token.mock.allowance + .withArgs(sender.address, swapERC20.address) + .returns(senderAmount) + await erc20token.mock.allowance + .withArgs(signer.address, swapERC20.address) + .returns(signerAmount) +} + +async function setUpBalances(senderAmount, signerAmount) { + await erc20token.mock.balanceOf.withArgs(sender.address).returns(senderAmount) + await erc20token.mock.balanceOf.withArgs(signer.address).returns(signerAmount) +} + +describe('BatchCall Integration', () => { + beforeEach(async () => { + snapshotId = await ethers.provider.send('evm_snapshot') + }) + + afterEach(async () => { + await ethers.provider.send('evm_revert', [snapshotId]) + }) + + before('deploy adapter and swap', async () => { + ;[deployer, sender, signer, affiliate, protocolFeeWallet, anyone] = + await ethers.getSigners() + erc20token = await deployMockContract(deployer, IERC20.abi) + await erc20token.mock.allowance.returns(DEFAULT_AMOUNT) + await erc20token.mock.balanceOf.returns(DEFAULT_AMOUNT) + await erc20token.mock.transferFrom.returns(true) + erc20adapter = await ( + await ethers.getContractFactory(ERC20_ADAPTER.abi, ERC20_ADAPTER.bytecode) + ).deploy() + await erc20adapter.deployed() + + erc721token = await deployMockContract(deployer, IERC721.abi) + await erc721token.mock.isApprovedForAll.returns(true) + await erc721token.mock.ownerOf.returns(sender.address) + await erc721token.mock[ + 'safeTransferFrom(address,address,uint256)' + ].returns() + erc721adapter = await ( + await ethers.getContractFactory( + ERC721_ADAPTER.abi, + ERC721_ADAPTER.bytecode + ) + ).deploy() + await erc721adapter.deployed() + swap = await ( + await ethers.getContractFactory(SWAP.abi, SWAP.bytecode) + ).deploy( + [erc20adapter.address, erc721adapter.address], + TokenKinds.ERC20, + PROTOCOL_FEE, + protocolFeeWallet.address + ) + await swap.deployed() + + swapERC20 = await ( + await ethers.getContractFactory(SWAP_ERC20.abi, SWAP_ERC20.bytecode) + ).deploy( + PROTOCOL_FEE, + PROTOCOL_FEE_LIGHT, + protocolFeeWallet.address, + BONUS_SCALE, + BONUS_MAX + ) + await swapERC20.deployed() + + batchCall = await (await ethers.getContractFactory('BatchCall')).deploy() + await batchCall.deployed() + }) + + describe('checks order validity', () => { + it('valid orders are marked valid', async () => { + await setUpAllowances(DEFAULT_BALANCE, DEFAULT_BALANCE) + await setUpBalances(DEFAULT_BALANCE, DEFAULT_BALANCE) + const orders = [ + await createSignedOrder({}, signer), + await createSignedOrder({}, signer), + await createSignedOrder({}, signer), + ] + const orderValidities = await batchCall + .connect(sender) + .checkOrders(sender.address, orders, swap.address) + expect(orderValidities.toString()).to.equal([true, true, true].toString()) + }) + + it('valid orders ERC20 are marked valid', async () => { + await setUpAllowances(DEFAULT_BALANCE, DEFAULT_BALANCE) + await setUpBalances(DEFAULT_BALANCE, DEFAULT_BALANCE) + const ERC20orders = [ + await createSignedOrderERC20({}, signer), + await createSignedOrderERC20({}, signer), + await createSignedOrderERC20({}, signer), + ] + const orderValidities = await batchCall + .connect(sender) + .checkOrdersERC20(sender.address, ERC20orders, swapERC20.address) + expect(orderValidities.toString()).to.equal([true, true, true].toString()) + }) + + it('invalid orders are marked invalid', async () => { + await setUpAllowances(0, 0) + await setUpBalances(0, 0) + const orders = [ + await createSignedOrder({}, signer), + await createSignedOrder({}, signer), + await createSignedOrder({}, signer), + ] + const orderValidities = await batchCall + .connect(sender) + .checkOrders(sender.address, orders, swap.address) + expect(orderValidities.toString()).to.equal( + [false, false, false].toString() + ) + }) + + it('invalid orders ERC20 are marked invalid', async () => { + await setUpAllowances(0, 0) + await setUpBalances(0, 0) + const ERC20orders = [ + await createSignedOrderERC20({}, signer), + await createSignedOrderERC20({}, signer), + await createSignedOrderERC20({}, signer), + ] + const orderValidities = await batchCall + .connect(sender) + .checkOrdersERC20(sender.address, ERC20orders, swapERC20.address) + expect(orderValidities.toString()).to.equal( + [false, false, false].toString() + ) + }) + }) +}) diff --git a/source/balances/tsconfig.json b/source/batch-call/tsconfig.json similarity index 100% rename from source/balances/tsconfig.json rename to source/batch-call/tsconfig.json diff --git a/source/pool/deploys-blocks.js.d.ts b/source/pool/deploys-blocks.js.d.ts new file mode 100644 index 000000000..0d9723258 --- /dev/null +++ b/source/pool/deploys-blocks.js.d.ts @@ -0,0 +1 @@ +declare module '@airswap/pool/deploys-blocks.js' diff --git a/source/pool/deploys.js.d.ts b/source/pool/deploys.js.d.ts index 31683c18a..fe65925fc 100644 --- a/source/pool/deploys.js.d.ts +++ b/source/pool/deploys.js.d.ts @@ -1,2 +1 @@ declare module '@airswap/pool/deploys.js' -declare module '@airswap/pool/deploys-blocks.js' diff --git a/source/pool/package.json b/source/pool/package.json index e2e52b172..920a22fb5 100644 --- a/source/pool/package.json +++ b/source/pool/package.json @@ -31,7 +31,7 @@ "@openzeppelin/contracts": "^4.8.3" }, "devDependencies": { - "@airswap/constants": "4.1.8", + "@airswap/constants": "4.1.9-beta.0", "@airswap/metadata": "4.1.15", "@airswap/types": "4.1.3", "@airswap/utils": "4.1.12", diff --git a/source/pool/scripts/balances.js b/source/pool/scripts/balances.js index f1bd5ad48..173cc73f9 100644 --- a/source/pool/scripts/balances.js +++ b/source/pool/scripts/balances.js @@ -1,8 +1,8 @@ const { ethers } = require('hardhat') const { getKnownTokens } = require('@airswap/metadata') const { chainNames, ChainIds } = require('@airswap/constants') -const BalanceChecker = require('@airswap/balances/build/contracts/BalanceChecker.sol/BalanceChecker.json') -const balancesDeploys = require('@airswap/balances/deploys.js') +const BatchCall = require('@airswap/batch-call/build/contracts/BatchCall.sol/BatchCall.json') +const batchCallDeploys = require('@airswap/batch-call/deploys.js') const poolDeploys = require('../deploys.js') async function main() { @@ -16,7 +16,7 @@ async function main() { console.log('Network:', chainNames[chainId].toUpperCase()) console.log('\nPool:', poolDeploys[chainId]) - if (!balancesDeploys[chainId]) { + if (!batchCallDeploys[chainId]) { throw new Error('Unable to check balances on this chain.') } @@ -33,8 +33,8 @@ async function main() { console.log(`\nScanning non-zero balances for ${tokens.length} tokens...\n`) const balancesContract = new ethers.Contract( - balancesDeploys[chainId], - BalanceChecker.abi, + batchCallDeploys[chainId], + BatchCall.abi, account.provider ) diff --git a/source/pool/scripts/deploy.js b/source/pool/scripts/deploy.js index abfe460a4..264a2f0d8 100644 --- a/source/pool/scripts/deploy.js +++ b/source/pool/scripts/deploy.js @@ -10,7 +10,7 @@ const poolBlocks = require('../deploys-blocks.js') async function main() { await run('compile') - const config = await prettier.resolveConfig('../deploys.js') + const prettierConfig = await prettier.resolveConfig('../deploys.js') const [deployer] = await ethers.getSigners() const gasPrice = await deployer.getGasPrice() @@ -43,7 +43,7 @@ async function main() { './deploys.js', prettier.format( `module.exports = ${JSON.stringify(poolDeploys, null, '\t')}`, - { ...config, parser: 'babel' } + { ...prettierConfig, parser: 'babel' } ) ) poolBlocks[chainId] = ( @@ -53,7 +53,7 @@ async function main() { './deploys-blocks.js', prettier.format( `module.exports = ${JSON.stringify(poolBlocks, null, '\t')}`, - { ...config, parser: 'babel' } + { ...prettierConfig, parser: 'babel' } ) ) console.log(`Deployed: ${poolDeploys[chainId]} @ ${poolBlocks[chainId]}`) diff --git a/source/registry/deploys-blocks.js.d.ts b/source/registry/deploys-blocks.js.d.ts new file mode 100644 index 000000000..b263a6773 --- /dev/null +++ b/source/registry/deploys-blocks.js.d.ts @@ -0,0 +1 @@ +declare module '@airswap/registry/deploys-blocks.js' diff --git a/source/registry/deploys.js.d.ts b/source/registry/deploys.js.d.ts index adcadf673..13ee47dbe 100644 --- a/source/registry/deploys.js.d.ts +++ b/source/registry/deploys.js.d.ts @@ -1,2 +1 @@ declare module '@airswap/registry/deploys.js' -declare module '@airswap/registry/deploys-blocks.js' diff --git a/source/registry/package.json b/source/registry/package.json index eb7d5b158..8b275d5e7 100644 --- a/source/registry/package.json +++ b/source/registry/package.json @@ -32,7 +32,7 @@ "access": "public" }, "devDependencies": { - "@airswap/constants": "4.1.8", + "@airswap/constants": "4.1.9-beta.0", "@airswap/utils": "4.1.12", "prompt-confirm": "^2.0.4" } diff --git a/source/registry/scripts/deploy.js b/source/registry/scripts/deploy.js index bc2a42715..e069f3be9 100644 --- a/source/registry/scripts/deploy.js +++ b/source/registry/scripts/deploy.js @@ -16,7 +16,7 @@ const registryBlocks = require('../deploys-blocks.js') async function main() { await run('compile') - const config = await prettier.resolveConfig('../deploys.js') + const prettierConfig = await prettier.resolveConfig('../deploys.js') const [deployer] = await ethers.getSigners() const gasPrice = await deployer.getGasPrice() @@ -59,7 +59,7 @@ async function main() { './deploys.js', prettier.format( `module.exports = ${JSON.stringify(registryDeploys, null, '\t')}`, - { ...config, parser: 'babel' } + { ...prettierConfig, parser: 'babel' } ) ) registryBlocks[chainId] = ( @@ -69,7 +69,7 @@ async function main() { './deploys-blocks.js', prettier.format( `module.exports = ${JSON.stringify(registryBlocks, null, '\t')}`, - { ...config, parser: 'babel' } + { ...prettierConfig, parser: 'babel' } ) ) console.log( diff --git a/source/staking/contracts/Staking.sol b/source/staking/contracts/Staking.sol index 9bb541b4a..8622438e6 100644 --- a/source/staking/contracts/Staking.sol +++ b/source/staking/contracts/Staking.sol @@ -1,9 +1,10 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.17; +pragma solidity 0.8.23; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; +import "@openzeppelin/contracts/utils/math/Math.sol"; import "./interfaces/IStaking.sol"; /** @@ -227,13 +228,17 @@ contract Staking is IStaking, Ownable { */ function available(address _account) public view override returns (uint256) { Stake storage _selected = stakes[_account]; - uint256 _available = (_selected.balance * - (block.timestamp - _selected.timestamp)) / - (_selected.maturity - _selected.timestamp); - if (_available >= _selected.balance) { + if (_selected.maturity == _selected.timestamp) { return _selected.balance; } else { - return _available; + uint256 _available = (_selected.balance * + (block.timestamp - _selected.timestamp)) / + (_selected.maturity - _selected.timestamp); + if (_available >= _selected.balance) { + return _selected.balance; + } else { + return _available; + } } } @@ -276,10 +281,12 @@ contract Staking is IStaking, Ownable { if (_amount > available(_account)) revert AmountInvalid(_amount); uint256 nowAvailable = available(_account); _selected.balance = _selected.balance - _amount; - _selected.timestamp = + _selected.timestamp = Math.min( block.timestamp - - (((10000 - ((10000 * _amount) / nowAvailable)) * - (block.timestamp - _selected.timestamp)) / 10000); + (((10000 - ((10000 * _amount) / nowAvailable)) * + (block.timestamp - _selected.timestamp)) / 10000), + _selected.maturity + ); stakingToken.safeTransfer(_account, _amount); emit Transfer(_account, address(0), _amount); } diff --git a/source/staking/contracts/interfaces/IStaking.sol b/source/staking/contracts/interfaces/IStaking.sol index 638482ea9..79b0a8f1d 100644 --- a/source/staking/contracts/interfaces/IStaking.sol +++ b/source/staking/contracts/interfaces/IStaking.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.17; +pragma solidity 0.8.23; interface IStaking { struct Stake { diff --git a/source/staking/deploys-blocks.js b/source/staking/deploys-blocks.js index 3debd1e92..c9e43a672 100644 --- a/source/staking/deploys-blocks.js +++ b/source/staking/deploys-blocks.js @@ -1,5 +1,4 @@ module.exports = { - 1: 17215773, - 5: 9884607, - 11155111: 4509512, + 5: 10351547, + 11155111: 5059353, } diff --git a/source/staking/deploys-blocks.js.d.ts b/source/staking/deploys-blocks.js.d.ts new file mode 100644 index 000000000..c198bed6e --- /dev/null +++ b/source/staking/deploys-blocks.js.d.ts @@ -0,0 +1 @@ +declare module '@airswap/staking/deploys-blocks.js' diff --git a/source/staking/deploys.js b/source/staking/deploys.js index 9b502d561..0705d1544 100644 --- a/source/staking/deploys.js +++ b/source/staking/deploys.js @@ -1,5 +1,4 @@ module.exports = { - 1: '0x9fc450F9AfE2833Eb44f9A1369Ab3678D3929860', - 5: '0x3BeC6526366cb2C2A609eb2bCeC8A696C141a33e', - 11155111: '0x3BeC6526366cb2C2A609eb2bCeC8A696C141a33e', + 5: '0x147644781C1ccb078738ecced7B247AF0bD5Aa8b', + 11155111: '0x147644781C1ccb078738ecced7B247AF0bD5Aa8b', } diff --git a/source/staking/deploys.js.d.ts b/source/staking/deploys.js.d.ts index bab7d7390..e1f05bafa 100644 --- a/source/staking/deploys.js.d.ts +++ b/source/staking/deploys.js.d.ts @@ -1,2 +1 @@ declare module '@airswap/staking/deploys.js' -declare module '@airswap/staking/deploys-blocks.js' diff --git a/source/staking/package.json b/source/staking/package.json index ceef3b34f..abb7e8781 100644 --- a/source/staking/package.json +++ b/source/staking/package.json @@ -1,6 +1,6 @@ { "name": "@airswap/staking", - "version": "4.0.5", + "version": "4.1.0-beta.0", "description": "AirSwap: Stake Tokens", "license": "MIT", "repository": { diff --git a/source/staking/scripts/config.js b/source/staking/scripts/config.js new file mode 100644 index 000000000..e0129ff4f --- /dev/null +++ b/source/staking/scripts/config.js @@ -0,0 +1,24 @@ +const { ChainIds, stakingTokenAddresses } = require('@airswap/constants') +module.exports = { + [ChainIds.MAINNET]: { + name: 'Staked AST', + symbol: 'sAST', + stakingToken: stakingTokenAddresses[ChainIds.MAINNET], + stakingDuration: 60 * 60 * 24 * 7 * 20, // 20 WEEKS + minDurationChangeDelay: 60 * 60 * 24 * 7, // 1 WEEK + }, + [ChainIds.GOERLI]: { + name: 'Staked AST (Goerli)', + symbol: 'sAST (Goerli)', + stakingToken: stakingTokenAddresses[ChainIds.GOERLI], + stakingDuration: 60 * 60, // 1 HOUR + minDurationChangeDelay: 60, // 1 MINUTE + }, + [ChainIds.SEPOLIA]: { + name: 'Staked AST (Sepolia)', + symbol: 'sAST (Sepolia)', + stakingToken: stakingTokenAddresses[ChainIds.SEPOLIA], + stakingDuration: 60 * 60, // 1 HOUR + minDurationChangeDelay: 60, // 1 MINUTE + }, +} diff --git a/source/staking/scripts/deploy.js b/source/staking/scripts/deploy.js index 893ae714a..c51e49e0d 100644 --- a/source/staking/scripts/deploy.js +++ b/source/staking/scripts/deploy.js @@ -3,20 +3,15 @@ const fs = require('fs') const prettier = require('prettier') const Confirm = require('prompt-confirm') const { ethers, run } = require('hardhat') -const { - chainNames, - chainLabels, - stakingTokenAddresses, - ChainIds, -} = require('@airswap/constants') +const { chainNames, chainLabels, ChainIds } = require('@airswap/constants') const { getReceiptUrl } = require('@airswap/utils') const stakingDeploys = require('../deploys.js') const stakingBlocks = require('../deploys-blocks.js') +const config = require('./config.js') async function main() { await run('compile') - const config = await prettier.resolveConfig('../deploys.js') - + const prettierConfig = await prettier.resolveConfig('../deploys.js') const [deployer] = await ethers.getSigners() const gasPrice = await deployer.getGasPrice() const chainId = await deployer.getChainId() @@ -28,11 +23,13 @@ async function main() { console.log(`Network: ${chainNames[chainId].toUpperCase()}`) console.log(`Gas price: ${gasPrice / 10 ** 9} gwei\n`) - const name = 'Staked AST' - const symbol = 'sAST' - const stakingToken = stakingTokenAddresses[chainId] - const stakingDuration = 60 * 60 * 24 * 7 * 20 // Twenty Weeks - const minDurationChangeDelay = 60 * 60 * 24 * 7 // One Week + const { + name, + symbol, + stakingToken, + stakingDuration, + minDurationChangeDelay, + } = config[chainId] console.log(`\nname: ${name}`) console.log(`symbol: ${symbol}`) @@ -61,7 +58,7 @@ async function main() { './deploys.js', prettier.format( `module.exports = ${JSON.stringify(stakingDeploys, null, '\t')}`, - { ...config, parser: 'babel' } + { ...prettierConfig, parser: 'babel' } ) ) stakingBlocks[chainId] = ( @@ -71,7 +68,7 @@ async function main() { './deploys-blocks.js', prettier.format( `module.exports = ${JSON.stringify(stakingBlocks, null, '\t')}`, - { ...config, parser: 'babel' } + { ...prettierConfig, parser: 'babel' } ) ) console.log( diff --git a/source/staking/scripts/verify.js b/source/staking/scripts/verify.js index faebff6f9..cce4d78a0 100644 --- a/source/staking/scripts/verify.js +++ b/source/staking/scripts/verify.js @@ -1,7 +1,8 @@ /* eslint-disable no-console */ const { ethers, run } = require('hardhat') const stakingDeploys = require('../deploys.js') -const { chainNames, stakingTokenAddresses } = require('@airswap/constants') +const { chainNames } = require('@airswap/constants') +const config = require('./config.js') async function main() { await run('compile') @@ -9,11 +10,13 @@ async function main() { console.log(`Deployer: ${deployer.address}`) const chainId = await deployer.getChainId() - const name = 'Staked AST' - const symbol = 'sAST' - const stakingToken = stakingTokenAddresses[chainId] - const stakingDuration = 60 * 60 * 24 * 7 * 20 // Twenty Weeks - const minDurationChangeDelay = 60 * 60 * 24 * 7 // One Week + const { + name, + symbol, + stakingToken, + stakingDuration, + minDurationChangeDelay, + } = config[chainId] console.log(`Contract: ${stakingDeploys[chainId]}`) console.log(`Verifying on ${chainNames[chainId].toUpperCase()}`) diff --git a/source/staking/test/Staking.js b/source/staking/test/Staking.js index 642fa2182..1d99aeb1e 100644 --- a/source/staking/test/Staking.js +++ b/source/staking/test/Staking.js @@ -339,6 +339,109 @@ describe('Staking Unit', () => { expect(userStakes.balance).to.equal(90) }) + it('successful successive maximum unstaking', async () => { + await token.mock.transferFrom.returns(true) + await token.mock.transfer.returns(true) + await staking.connect(account1).stake('100') + + // move 10 seconds forward - 10% unstakeable + await ethers.provider.send('evm_increaseTime', [10]) + await ethers.provider.send('evm_mine') + + await staking.connect(account1).unstake('11') + const userStakes = await staking + .connect(account1) + .getStakes(account1.address) + + expect(userStakes.balance).to.equal(89) + + // move 20 seconds forward - 20% unstakeable + await ethers.provider.send('evm_increaseTime', [20]) + await ethers.provider.send('evm_mine') + await staking.connect(account1).unstake('21') + const userStakes2 = await staking + .connect(account1) + .getStakes(account1.address) + + expect(userStakes2.balance).to.equal(68) + }) + + it('successful partial unstaking after stake maturity', async () => { + await token.mock.transferFrom.returns(true) + await token.mock.transfer.returns(true) + await staking.connect(account1).stake('100') + + // move 1000 seconds forward - 100% unstakeable + await ethers.provider.send('evm_increaseTime', [999]) + await ethers.provider.send('evm_mine') + + await staking.connect(account1).unstake('10') + const userStakes = await staking + .connect(account1) + .getStakes(account1.address) + + expect(userStakes.balance).to.equal(90) + + await staking.connect(account1).unstake('10') + const userStakes2 = await staking + .connect(account1) + .getStakes(account1.address) + + expect(userStakes2.balance).to.equal(80) + }) + + it('successful unstake after partial unstake and restake', async () => { + await token.mock.transferFrom.returns(true) + await token.mock.transfer.returns(true) + await staking.connect(account1).stake('100') + + // move 1000 seconds forward - 100% unstakeable + await ethers.provider.send('evm_increaseTime', [1000]) + await ethers.provider.send('evm_mine') + + // Unstake 10 + await staking.connect(account1).unstake('10') + const userStakes = await staking + .connect(account1) + .getStakes(account1.address) + + expect(userStakes.balance).to.equal(90) + + // Stake 100 + await staking.connect(account1).stake('100') + + const userStakes2 = await staking + .connect(account1) + .getStakes(account1.address) + + expect(userStakes2.balance).to.equal(190) + + // Unstake remainder of unstakable amount + await staking.connect(account1).unstake('90') + + const userStakes3 = await staking + .connect(account1) + .getStakes(account1.address) + + expect(userStakes3.balance).to.equal(100) + + // Cannot unstake the new amount immediately + await expect(staking.connect(account1).unstake('10')) + .to.be.revertedWith('AmountInvalid') + .withArgs(10) + + // move 10 seconds forward - 10% unstakeable + await ethers.provider.send('evm_increaseTime', [10]) + await ethers.provider.send('evm_mine') + + await staking.connect(account1).unstake('10') + const userStakes4 = await staking + .connect(account1) + .getStakes(account1.address) + + expect(userStakes4.balance).to.equal(90) + }) + it('successful extended stake and successful unstaking', async () => { await token.mock.transferFrom.returns(true) await token.mock.transfer.returns(true) diff --git a/source/swap-erc20/contracts/SwapERC20.sol b/source/swap-erc20/contracts/SwapERC20.sol index ce732cd14..65728ecef 100644 --- a/source/swap-erc20/contracts/SwapERC20.sol +++ b/source/swap-erc20/contracts/SwapERC20.sol @@ -1,9 +1,10 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.17; +pragma solidity 0.8.23; import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/utils/cryptography/EIP712.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +import "./interfaces/INoReturnERC20.sol"; import "./interfaces/ISwapERC20.sol"; /** @@ -45,8 +46,8 @@ contract SwapERC20 is ISwapERC20, Ownable, EIP712 { uint256 public protocolFee; uint256 public protocolFeeLight; address public protocolFeeWallet; - uint256 public discountScale; - uint256 public discountMax; + uint256 public bonusScale; + uint256 public bonusMax; address public stakingToken; /** @@ -54,21 +55,21 @@ contract SwapERC20 is ISwapERC20, Ownable, EIP712 { * @dev Sets domain and version for EIP712 signatures * @param _protocolFee uin256 fee to be assessed on swaps * @param _protocolFeeWallet address destination for fees - * @param _discountScale uin256 scale factor for discount - * @param _discountMax uint256 max discount percentage + * @param _bonusScale uin256 scale factor for bonus + * @param _bonusMax uint256 max bonus percentage */ constructor( uint256 _protocolFee, uint256 _protocolFeeLight, address _protocolFeeWallet, - uint256 _discountScale, - uint256 _discountMax + uint256 _bonusScale, + uint256 _bonusMax ) EIP712(DOMAIN_NAME, DOMAIN_VERSION) { if (_protocolFee >= FEE_DIVISOR) revert InvalidFee(); if (_protocolFeeLight >= FEE_DIVISOR) revert InvalidFeeLight(); if (_protocolFeeWallet == address(0)) revert InvalidFeeWallet(); - if (_discountMax > MAX_MAX) revert MaxTooHigh(); - if (_discountScale > MAX_SCALE) revert ScaleTooHigh(); + if (_bonusMax > MAX_MAX) revert MaxTooHigh(); + if (_bonusScale > MAX_SCALE) revert ScaleTooHigh(); DOMAIN_CHAIN_ID = block.chainid; DOMAIN_SEPARATOR = _domainSeparatorV4(); @@ -76,8 +77,8 @@ contract SwapERC20 is ISwapERC20, Ownable, EIP712 { protocolFee = _protocolFee; protocolFeeLight = _protocolFeeLight; protocolFeeWallet = _protocolFeeWallet; - discountMax = _discountMax; - discountScale = _discountScale; + bonusMax = _bonusMax; + bonusScale = _bonusScale; } /** @@ -132,7 +133,7 @@ contract SwapERC20 is ISwapERC20, Ownable, EIP712 { // Transfer token from signer to recipient IERC20(signerToken).safeTransferFrom(signerWallet, recipient, signerAmount); - // Calculate and transfer protocol fee and any discount + // Calculate and transfer protocol fee _transferProtocolFee(signerToken, signerWallet, signerAmount); // Emit event @@ -191,7 +192,7 @@ contract SwapERC20 is ISwapERC20, Ownable, EIP712 { // Transfer token from signer to recipient IERC20(signerToken).safeTransferFrom(signerWallet, recipient, signerAmount); - // Calculate and transfer protocol fee and any discount + // Calculate and transfer protocol fee _transferProtocolFee(signerToken, signerWallet, signerAmount); // Emit event @@ -199,7 +200,8 @@ contract SwapERC20 is ISwapERC20, Ownable, EIP712 { } /** - * @notice Swap Atomic ERC20 Swap (Low Gas Usage) + * @notice Swap Atomic ERC20 Swap (Minimal Gas) + * @dev No transfer checks. Only use with known tokens. * @param nonce uint256 Unique and should be sequential * @param expiry uint256 Expiry in seconds since 1 January 1970 * @param signerWallet address Wallet of the signer @@ -269,13 +271,21 @@ contract SwapERC20 is ISwapERC20, Ownable, EIP712 { } // Transfer token from sender to signer - IERC20(senderToken).transferFrom(msg.sender, signerWallet, senderAmount); + INoReturnERC20(senderToken).transferFrom( + msg.sender, + signerWallet, + senderAmount + ); // Transfer token from signer to sender - IERC20(signerToken).transferFrom(signerWallet, msg.sender, signerAmount); + INoReturnERC20(signerToken).transferFrom( + signerWallet, + msg.sender, + signerAmount + ); // Transfer protocol fee from signer to fee wallet - IERC20(signerToken).transferFrom( + INoReturnERC20(signerToken).transferFrom( signerWallet, protocolFeeWallet, (signerAmount * protocolFeeLight) / FEE_DIVISOR @@ -286,7 +296,7 @@ contract SwapERC20 is ISwapERC20, Ownable, EIP712 { } /** - * @notice Set the fee + * @notice Set the protocol fee * @param _protocolFee uint256 Value of the fee in basis points */ function setProtocolFee(uint256 _protocolFee) external onlyOwner { @@ -297,7 +307,7 @@ contract SwapERC20 is ISwapERC20, Ownable, EIP712 { } /** - * @notice Set the light fee + * @notice Set the light protocol fee * @param _protocolFeeLight uint256 Value of the fee in basis points */ function setProtocolFeeLight(uint256 _protocolFeeLight) external onlyOwner { @@ -308,7 +318,7 @@ contract SwapERC20 is ISwapERC20, Ownable, EIP712 { } /** - * @notice Set the fee wallet + * @notice Set the protocol fee wallet * @param _protocolFeeWallet address Wallet to transfer fee to */ function setProtocolFeeWallet(address _protocolFeeWallet) external onlyOwner { @@ -319,29 +329,29 @@ contract SwapERC20 is ISwapERC20, Ownable, EIP712 { } /** - * @notice Set max + * @notice Set staking bonus max * @dev Only owner - * @param _discountMax uint256 + * @param _bonusMax uint256 */ - function setDiscountMax(uint256 _discountMax) external onlyOwner { - if (_discountMax > MAX_MAX) revert MaxTooHigh(); - discountMax = _discountMax; - emit SetDiscountMax(_discountMax); + function setBonusMax(uint256 _bonusMax) external onlyOwner { + if (_bonusMax > MAX_MAX) revert MaxTooHigh(); + bonusMax = _bonusMax; + emit SetBonusMax(_bonusMax); } /** - * @notice Set scale + * @notice Set staking bonus scale * @dev Only owner - * @param _discountScale uint256 + * @param _bonusScale uint256 */ - function setDiscountScale(uint256 _discountScale) external onlyOwner { - if (_discountScale > MAX_SCALE) revert ScaleTooHigh(); - discountScale = _discountScale; - emit SetDiscountScale(_discountScale); + function setBonusScale(uint256 _bonusScale) external onlyOwner { + if (_bonusScale > MAX_SCALE) revert ScaleTooHigh(); + bonusScale = _bonusScale; + emit SetBonusScale(_bonusScale); } /** - * @notice Set the staking token + * @notice Set staking token * @param _stakingToken address Token to check balances on */ function setStaking(address _stakingToken) external onlyOwner { @@ -526,16 +536,16 @@ contract SwapERC20 is ISwapERC20, Ownable, EIP712 { } /** - * @notice Calculate discount from staking balance + * @notice Calculate bonus from staking balance * @param stakingBalance uint256 * @param feeAmount uint256 */ - function calculateDiscount( + function calculateBonus( uint256 stakingBalance, uint256 feeAmount ) public view returns (uint256) { - uint256 divisor = (uint256(10) ** discountScale) + stakingBalance; - return (discountMax * stakingBalance * feeAmount) / divisor / MAX_MAX; + uint256 divisor = (uint256(10) ** bonusScale) + stakingBalance; + return (bonusMax * stakingBalance * feeAmount) / divisor / MAX_MAX; } /** @@ -550,11 +560,11 @@ contract SwapERC20 is ISwapERC20, Ownable, EIP712 { // Transfer fee from signer to feeWallet uint256 feeAmount = (amount * protocolFee) / FEE_DIVISOR; if (stakingToken != address(0) && feeAmount > 0) { - uint256 discountAmount = calculateDiscount( + uint256 bonusAmount = calculateBonus( IERC20(stakingToken).balanceOf(wallet), feeAmount ); - return feeAmount - discountAmount; + return feeAmount - bonusAmount; } return feeAmount; } @@ -707,7 +717,7 @@ contract SwapERC20 is ISwapERC20, Ownable, EIP712 { } /** - * @notice Calculates and transfers protocol fee and discount + * @notice Calculates and transfers protocol fee and bonus * @param sourceToken address * @param sourceWallet address * @param amount uint256 @@ -720,26 +730,26 @@ contract SwapERC20 is ISwapERC20, Ownable, EIP712 { // Transfer fee from signer to feeWallet uint256 feeAmount = (amount * protocolFee) / FEE_DIVISOR; if (feeAmount > 0) { - uint256 discountAmount = 0; + uint256 bonusAmount = 0; if (stakingToken != address(0)) { - // Only check discount if staking is set - discountAmount = calculateDiscount( + // Only check bonus if staking is set + bonusAmount = calculateBonus( IERC20(stakingToken).balanceOf(msg.sender), feeAmount ); } - if (discountAmount > 0) { + if (bonusAmount > 0) { // Transfer fee from signer to sender IERC20(sourceToken).safeTransferFrom( sourceWallet, msg.sender, - discountAmount + bonusAmount ); // Transfer fee from signer to feeWallet IERC20(sourceToken).safeTransferFrom( sourceWallet, protocolFeeWallet, - feeAmount - discountAmount + feeAmount - bonusAmount ); } else { IERC20(sourceToken).safeTransferFrom( diff --git a/source/swap-erc20/contracts/interfaces/INoReturnERC20.sol b/source/swap-erc20/contracts/interfaces/INoReturnERC20.sol new file mode 100644 index 000000000..798013daa --- /dev/null +++ b/source/swap-erc20/contracts/interfaces/INoReturnERC20.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.23; + +interface INoReturnERC20 { + function transferFrom(address from, address to, uint value) external; +} diff --git a/source/swap-erc20/contracts/interfaces/ISwapERC20.sol b/source/swap-erc20/contracts/interfaces/ISwapERC20.sol index 32b6cf6a4..2d1861776 100644 --- a/source/swap-erc20/contracts/interfaces/ISwapERC20.sol +++ b/source/swap-erc20/contracts/interfaces/ISwapERC20.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.17; +pragma solidity 0.8.23; interface ISwapERC20 { struct OrderERC20 { @@ -24,8 +24,8 @@ interface ISwapERC20 { event SetProtocolFee(uint256 protocolFee); event SetProtocolFeeLight(uint256 protocolFeeLight); event SetProtocolFeeWallet(address indexed feeWallet); - event SetDiscountScale(uint256 discountScale); - event SetDiscountMax(uint256 discountMax); + event SetBonusScale(uint256 bonusScale); + event SetBonusMax(uint256 bonusMax); event SetStaking(address indexed staking); error ChainIdChanged(); @@ -89,6 +89,20 @@ interface ISwapERC20 { function cancel(uint256[] calldata nonces) external; + function check( + address senderWallet, + uint256 nonce, + uint256 expiry, + address signerWallet, + address signerToken, + uint256 signerAmount, + address senderToken, + uint256 senderAmount, + uint8 v, + bytes32 r, + bytes32 s + ) external view returns (uint256, bytes32[] memory); + function nonceUsed(address, uint256) external view returns (bool); function authorized(address) external view returns (address); diff --git a/source/swap-erc20/deploys-blocks.js b/source/swap-erc20/deploys-blocks.js index 99d6f92af..e6d00e7b8 100644 --- a/source/swap-erc20/deploys-blocks.js +++ b/source/swap-erc20/deploys-blocks.js @@ -1,21 +1,4 @@ module.exports = { - 1: 18319195, - 5: 9841536, - 30: 5711587, - 31: 4370691, - 40: 305712483, - 41: 262212751, - 56: 32477948, - 97: 34077869, - 137: 48547131, - 8453: 5071323, - 42161: 139313165, - 43113: 26648854, - 43114: 36269658, - 59140: 1694102, - 59144: 602164, - 80001: 41044777, - 84531: 10869146, - 421613: 46764380, - 11155111: 4508898, + 5: 10357890, + 11155111: 5067066, } diff --git a/source/swap-erc20/deploys-blocks.js.d.ts b/source/swap-erc20/deploys-blocks.js.d.ts new file mode 100644 index 000000000..ea71086cb --- /dev/null +++ b/source/swap-erc20/deploys-blocks.js.d.ts @@ -0,0 +1 @@ +declare module '@airswap/swap-erc20/deploys-blocks.js' diff --git a/source/swap-erc20/deploys.js b/source/swap-erc20/deploys.js index e01fac37d..6ca1e2a60 100644 --- a/source/swap-erc20/deploys.js +++ b/source/swap-erc20/deploys.js @@ -1,21 +1,4 @@ module.exports = { - 1: '0x0C9b31Dc37718417608CE22bb1ba940f702BF90B', - 5: '0x0C9b31Dc37718417608CE22bb1ba940f702BF90B', - 30: '0x0C9b31Dc37718417608CE22bb1ba940f702BF90B', - 31: '0x0C9b31Dc37718417608CE22bb1ba940f702BF90B', - 40: '0x0C9b31Dc37718417608CE22bb1ba940f702BF90B', - 41: '0x0C9b31Dc37718417608CE22bb1ba940f702BF90B', - 56: '0x0C9b31Dc37718417608CE22bb1ba940f702BF90B', - 97: '0x0C9b31Dc37718417608CE22bb1ba940f702BF90B', - 137: '0x0C9b31Dc37718417608CE22bb1ba940f702BF90B', - 8453: '0x0C9b31Dc37718417608CE22bb1ba940f702BF90B', - 42161: '0x0C9b31Dc37718417608CE22bb1ba940f702BF90B', - 43113: '0x0C9b31Dc37718417608CE22bb1ba940f702BF90B', - 43114: '0x0C9b31Dc37718417608CE22bb1ba940f702BF90B', - 59140: '0x0C9b31Dc37718417608CE22bb1ba940f702BF90B', - 59144: '0x0C9b31Dc37718417608CE22bb1ba940f702BF90B', - 80001: '0x0C9b31Dc37718417608CE22bb1ba940f702BF90B', - 84531: '0x0C9b31Dc37718417608CE22bb1ba940f702BF90B', - 421613: '0x0C9b31Dc37718417608CE22bb1ba940f702BF90B', - 11155111: '0x0C9b31Dc37718417608CE22bb1ba940f702BF90B', + 5: '0xb0B0Aae54B4336B359201EDfB45C4dB4879e55a5', + 11155111: '0xb0B0Aae54B4336B359201EDfB45C4dB4879e55a5', } diff --git a/source/swap-erc20/deploys.js.d.ts b/source/swap-erc20/deploys.js.d.ts index 0d8be5990..6eb974286 100644 --- a/source/swap-erc20/deploys.js.d.ts +++ b/source/swap-erc20/deploys.js.d.ts @@ -1,2 +1 @@ declare module '@airswap/swap-erc20/deploys.js' -declare module '@airswap/swap-erc20/deploys-blocks.js' diff --git a/source/swap-erc20/package.json b/source/swap-erc20/package.json index 90b6351bd..fd4c90780 100644 --- a/source/swap-erc20/package.json +++ b/source/swap-erc20/package.json @@ -1,6 +1,6 @@ { "name": "@airswap/swap-erc20", - "version": "4.1.6", + "version": "4.1.7-beta.0", "description": "AirSwap: Atomic ERC20 Token Swap", "license": "MIT", "repository": { @@ -29,8 +29,8 @@ "@openzeppelin/contracts": "^4.8.3" }, "devDependencies": { - "@airswap/constants": "4.1.8", - "@airswap/staking": "4.0.5", + "@airswap/constants": "4.1.9-beta.0", + "@airswap/staking": "4.1.0-beta.0", "@airswap/types": "4.1.3", "@airswap/utils": "4.1.12", "prompt-confirm": "^2.0.4" diff --git a/source/swap-erc20/scripts/config.js b/source/swap-erc20/scripts/config.js new file mode 100644 index 000000000..a37ed57ee --- /dev/null +++ b/source/swap-erc20/scripts/config.js @@ -0,0 +1,10 @@ +const { ChainIds } = require('@airswap/constants') + +module.exports = { + [ChainIds.MAINNET]: { + protocolFee: 7, + protocolFeeLight: 7, + bonusScale: 10, + bonusMax: 100, + }, +} diff --git a/source/swap-erc20/scripts/deploy.js b/source/swap-erc20/scripts/deploy.js index 8b7c6806c..28c58cf7e 100644 --- a/source/swap-erc20/scripts/deploy.js +++ b/source/swap-erc20/scripts/deploy.js @@ -14,10 +14,11 @@ const { const { getReceiptUrl } = require('@airswap/utils') const swapERC20Deploys = require('../deploys.js') const swapERC20Blocks = require('../deploys-blocks.js') +const config = require('./config.js') async function main() { await run('compile') - const config = await prettier.resolveConfig('../deploys.js') + const prettierConfig = await prettier.resolveConfig('../deploys.js') const [deployer] = await ethers.getSigners() const gasPrice = await deployer.getGasPrice() @@ -34,10 +35,18 @@ async function main() { if (protocolFeeReceiverAddresses[chainId]) { protocolFeeReceiver = protocolFeeReceiverAddresses[chainId] } - const protocolFee = 7 - const protocolFeeLight = 7 - const discountScale = 10 - const discountMax = 100 + + let protocolFee + let protocolFeeLight + let bonusScale + let bonusMax + + if (config[chainId]) { + ;({ protocolFee, protocolFeeLight, bonusScale, bonusMax } = config[chainId]) + } else { + ;({ protocolFee, protocolFeeLight, bonusScale, bonusMax } = + config[ChainIds.MAINNET]) + } console.log(`protocolFee: ${protocolFee}`) console.log(`protocolFeeLight: ${protocolFeeLight}`) @@ -50,8 +59,8 @@ async function main() { protocolFee, protocolFeeLight, protocolFeeReceiver, - discountScale, - discountMax, + bonusScale, + bonusMax, { gasPrice, } @@ -67,7 +76,7 @@ async function main() { './deploys.js', prettier.format( `module.exports = ${JSON.stringify(swapERC20Deploys, null, '\t')}`, - { ...config, parser: 'babel' } + { ...prettierConfig, parser: 'babel' } ) ) swapERC20Blocks[chainId] = ( @@ -77,7 +86,7 @@ async function main() { './deploys-blocks.js', prettier.format( `module.exports = ${JSON.stringify(swapERC20Blocks, null, '\t')}`, - { ...config, parser: 'babel' } + { ...prettierConfig, parser: 'babel' } ) ) console.log( diff --git a/source/swap-erc20/scripts/verify.js b/source/swap-erc20/scripts/verify.js index c37daafc7..c178b3c04 100644 --- a/source/swap-erc20/scripts/verify.js +++ b/source/swap-erc20/scripts/verify.js @@ -2,10 +2,12 @@ const { ethers, run } = require('hardhat') const poolDeploys = require('@airswap/pool/deploys.js') const { + ChainIds, chainNames, protocolFeeReceiverAddresses, } = require('@airswap/constants') const swapERC20Deploys = require('../deploys.js') +const config = require('./config.js') async function main() { await run('compile') @@ -18,10 +20,18 @@ async function main() { if (protocolFeeReceiverAddresses[chainId]) { protocolFeeReceiver = protocolFeeReceiverAddresses[chainId] } - const protocolFee = 7 - const protocolFeeLight = 7 - const discountScale = 10 - const discountMax = 100 + + let protocolFee + let protocolFeeLight + let bonusScale + let bonusMax + + if (config[chainId]) { + ;({ protocolFee, protocolFeeLight, bonusScale, bonusMax } = config[chainId]) + } else { + ;({ protocolFee, protocolFeeLight, bonusScale, bonusMax } = + config[ChainIds.MAINNET]) + } console.log(`Verifying on ${chainNames[chainId].toUpperCase()}`) await run('verify:verify', { @@ -30,8 +40,8 @@ async function main() { protocolFee, protocolFeeLight, protocolFeeReceiver, - discountScale, - discountMax, + bonusScale, + bonusMax, ], }) } diff --git a/source/swap-erc20/test/SwapERC20.js b/source/swap-erc20/test/SwapERC20.js index 80a7c2f4f..6350e2f88 100644 --- a/source/swap-erc20/test/SwapERC20.js +++ b/source/swap-erc20/test/SwapERC20.js @@ -27,8 +27,8 @@ describe('SwapERC20 Unit', () => { const PROTOCOL_FEE = '30' const PROTOCOL_FEE_LIGHT = '7' const HIGHER_FEE = '50' - const REBATE_SCALE = '10' - const REBATE_MAX = '100' + const BONUS_SCALE = '10' + const BONUS_MAX = '100' const FEE_DIVISOR = '10000' const DEFAULT_AMOUNT = '10000' const DEFAULT_BALANCE = '100000' @@ -126,8 +126,8 @@ describe('SwapERC20 Unit', () => { PROTOCOL_FEE, PROTOCOL_FEE_LIGHT, protocolFeeWallet.address, - REBATE_SCALE, - REBATE_MAX + BONUS_SCALE, + BONUS_MAX ) await swap.deployed() }) @@ -148,8 +148,8 @@ describe('SwapERC20 Unit', () => { PROTOCOL_FEE, PROTOCOL_FEE_LIGHT, ADDRESS_ZERO, - REBATE_SCALE, - REBATE_MAX + BONUS_SCALE, + BONUS_MAX ) ).to.be.revertedWith('InvalidFeeWallet') }) @@ -162,8 +162,8 @@ describe('SwapERC20 Unit', () => { 100000000000, PROTOCOL_FEE_LIGHT, protocolFeeWallet.address, - REBATE_SCALE, - REBATE_MAX + BONUS_SCALE, + BONUS_MAX ) ).to.be.revertedWith('InvalidFee') }) @@ -176,13 +176,13 @@ describe('SwapERC20 Unit', () => { PROTOCOL_FEE, 100000000000, protocolFeeWallet.address, - REBATE_SCALE, - REBATE_MAX + BONUS_SCALE, + BONUS_MAX ) ).to.be.revertedWith('InvalidFeeLight') }) - it('test invalid discount scale', async () => { + it('test invalid bonus scale', async () => { await expect( ( await ethers.getContractFactory('SwapERC20') @@ -190,13 +190,13 @@ describe('SwapERC20 Unit', () => { PROTOCOL_FEE, PROTOCOL_FEE_LIGHT, protocolFeeWallet.address, - REBATE_SCALE + 1, - REBATE_MAX + BONUS_SCALE + 1, + BONUS_MAX ) ).to.be.revertedWith('ScaleTooHigh') }) - it('test invalid discount maximum', async () => { + it('test invalid bonus maximum', async () => { await expect( ( await ethers.getContractFactory('SwapERC20') @@ -204,8 +204,8 @@ describe('SwapERC20 Unit', () => { PROTOCOL_FEE, PROTOCOL_FEE_LIGHT, protocolFeeWallet.address, - REBATE_SCALE, - REBATE_MAX + 1 + BONUS_SCALE, + BONUS_MAX + 1 ) ).to.be.revertedWith('MaxTooHigh') }) @@ -248,34 +248,36 @@ describe('SwapERC20 Unit', () => { swap.connect(deployer).setProtocolFeeWallet(protocolFeeWallet.address) ).to.emit(swap, 'SetProtocolFeeWallet') }) - it('test setDiscountScale', async () => { - await expect( - swap.connect(deployer).setDiscountScale(REBATE_SCALE) - ).to.emit(swap, 'SetDiscountScale') + it('test setBonusScale', async () => { + await expect(swap.connect(deployer).setBonusScale(BONUS_SCALE)).to.emit( + swap, + 'SetBonusScale' + ) }) - it('test setDiscountScale with invalid input', async () => { + it('test setBonusScale with invalid input', async () => { await expect( - swap.connect(deployer).setDiscountScale(REBATE_SCALE + 1) + swap.connect(deployer).setBonusScale(BONUS_SCALE + 1) ).to.be.revertedWith('ScaleTooHigh') }) - it('test setDiscountScale as non-owner', async () => { + it('test setBonusScale as non-owner', async () => { await expect( - swap.connect(anyone).setDiscountScale(REBATE_SCALE) + swap.connect(anyone).setBonusScale(BONUS_SCALE) ).to.be.revertedWith('Ownable: caller is not the owner') }) - it('test setDiscountMax', async () => { - await expect( - await swap.connect(deployer).setDiscountMax(REBATE_MAX) - ).to.emit(swap, 'SetDiscountMax') + it('test setBonusMax', async () => { + await expect(await swap.connect(deployer).setBonusMax(BONUS_MAX)).to.emit( + swap, + 'SetBonusMax' + ) }) - it('test setDiscountMax with invalid input', async () => { + it('test setBonusMax with invalid input', async () => { await expect( - swap.connect(deployer).setDiscountMax(REBATE_MAX + 1) + swap.connect(deployer).setBonusMax(BONUS_MAX + 1) ).to.be.revertedWith('MaxTooHigh') }) - it('test setDiscountMax as non-owner', async () => { + it('test setBonusMax as non-owner', async () => { await expect( - swap.connect(anyone).setDiscountMax(REBATE_MAX) + swap.connect(anyone).setBonusMax(BONUS_MAX) ).to.be.revertedWith('Ownable: caller is not the owner') }) it('test setStaking', async () => { @@ -304,13 +306,13 @@ describe('SwapERC20 Unit', () => { swap, 'SetStaking' ) - const discount = await swap + const bonus = await swap .connect(deployer) - .calculateDiscount(STAKING_BALANCE, initialFeeAmount) + .calculateBonus(STAKING_BALANCE, initialFeeAmount) const actualFeeAmount = await swap .connect(deployer) .calculateProtocolFee(sender.address, DEFAULT_AMOUNT) - expect(actualFeeAmount).to.equal(initialFeeAmount - discount) + expect(actualFeeAmount).to.equal(initialFeeAmount - bonus) }) it('test calculateProtocolFee with protocol fee as zero', async () => { const zeroProtocolFee = 0 @@ -320,13 +322,13 @@ describe('SwapERC20 Unit', () => { ) await swap.connect(deployer).setProtocolFee(zeroProtocolFee) const initialFeeAmount = (DEFAULT_AMOUNT * zeroProtocolFee) / FEE_DIVISOR - const discount = await swap + const bonus = await swap .connect(deployer) - .calculateDiscount(STAKING_BALANCE, initialFeeAmount) + .calculateBonus(STAKING_BALANCE, initialFeeAmount) const actualFeeAmount = await swap .connect(deployer) .calculateProtocolFee(sender.address, DEFAULT_AMOUNT) - expect(actualFeeAmount).to.equal(initialFeeAmount - discount) + expect(actualFeeAmount).to.equal(initialFeeAmount - bonus) }) }) diff --git a/source/swap-erc20/test/SwapERC20Integration.js b/source/swap-erc20/test/SwapERC20Integration.js index 0b519a993..b78305dc1 100644 --- a/source/swap-erc20/test/SwapERC20Integration.js +++ b/source/swap-erc20/test/SwapERC20Integration.js @@ -21,8 +21,8 @@ describe('SwapERC20 Integration', () => { let protocolFeeWallet const CHAIN_ID = 31337 - const DISCOUNT_SCALE = '10' - const DISCOUNT_MAX = '100' + const BONUS_SCALE = '10' + const BONUS_MAX = '100' const PROTOCOL_FEE = '30' const PROTOCOL_FEE_LIGHT = '7' const DEFAULT_AMOUNT = '10000' @@ -89,8 +89,8 @@ describe('SwapERC20 Integration', () => { PROTOCOL_FEE, PROTOCOL_FEE_LIGHT, protocolFeeWallet.address, - DISCOUNT_SCALE, - DISCOUNT_MAX + BONUS_SCALE, + BONUS_MAX ) await swap.deployed() @@ -98,7 +98,7 @@ describe('SwapERC20 Integration', () => { senderToken.connect(sender).approve(swap.address, 1000000) }) - describe('Test token holder discounts', async () => { + describe('Test token holder bonuss', async () => { it('test swap without staking', async () => { const order = await createSignedOrder({}, signer) @@ -119,7 +119,7 @@ describe('SwapERC20 Integration', () => { ) }) - it('test swap without discount', async () => { + it('test swap without bonus', async () => { const order = await createSignedOrder({}, signer) await expect(swap.connect(sender).swap(sender.address, ...order)).to.emit( @@ -139,7 +139,7 @@ describe('SwapERC20 Integration', () => { ) }) - it('test swap with discount', async () => { + it('test swap with bonus', async () => { await stakingToken.connect(sender).approve(staking.address, 10000000000) await staking.connect(sender).stake(10000000000) @@ -157,7 +157,7 @@ describe('SwapERC20 Integration', () => { // Expect full 30 to be taken from signer expect(await signerToken.balanceOf(signer.address)).to.equal('989970') - // Expect half of the fee to have gone to the sender as discount + // Expect half of the fee to have gone to the sender as bonus expect(await signerToken.balanceOf(sender.address)).to.equal('10015') // Expect half of the fee to have gone to the fee wallet diff --git a/source/swap/contracts/Swap.sol b/source/swap/contracts/Swap.sol index bd52e98f2..309c98fa9 100644 --- a/source/swap/contracts/Swap.sol +++ b/source/swap/contracts/Swap.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.17; +pragma solidity 0.8.23; import "@openzeppelin/contracts/access/Ownable2Step.sol"; import "@openzeppelin/contracts/utils/cryptography/EIP712.sol"; @@ -315,6 +315,10 @@ contract Swap is ISwap, Ownable2Step, EIP712 { errors[errCount] = "SignerBalanceLow"; errCount++; } + if (!signerTokenAdapter.hasValidParams(order.signer)) { + errors[errCount] = "AmountOrIDInvalid"; + errCount++; + } } IAdapter senderTokenAdapter = adapters[order.sender.kind]; @@ -347,6 +351,10 @@ contract Swap is ISwap, Ownable2Step, EIP712 { errors[errCount] = "SenderBalanceLow"; errCount++; } + if (!senderTokenAdapter.hasValidParams(order.signer)) { + errors[errCount] = "AmountOrIDInvalid"; + errCount++; + } if (order.sender.amount < order.affiliateAmount) { errors[errCount] = "AffiliateAmountInvalid"; errCount++; diff --git a/source/swap/contracts/adapters/ERC1155Adapter.sol b/source/swap/contracts/adapters/ERC1155Adapter.sol index 21a59aa50..2bb5c2464 100644 --- a/source/swap/contracts/adapters/ERC1155Adapter.sol +++ b/source/swap/contracts/adapters/ERC1155Adapter.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.17; +pragma solidity 0.8.23; import "../interfaces/IAdapter.sol"; import "@openzeppelin/contracts/token/ERC1155/IERC1155.sol"; @@ -12,8 +12,8 @@ contract ERC1155Adapter is IAdapter { bytes4 public constant interfaceId = 0xd9b67a26; /** - * @notice Function to wrap token transfer for different token types - * @param party Party from whom swap would be made + * @notice Checks allowance on an ERC1155 + * @param party Party params to check * @dev Use call: "msg.sender" is Swap contract */ function hasAllowance(Party calldata party) external view returns (bool) { @@ -22,14 +22,22 @@ contract ERC1155Adapter is IAdapter { } /** - * @notice Function to wrap token transfer for different token types - * @param party Party from whom swap would be made + * @notice Checks balance on an ERC1155 + * @param party Party params to check */ function hasBalance(Party calldata party) external view returns (bool) { return IERC1155(party.token).balanceOf(party.wallet, party.id) >= party.amount; } + /** + * @notice Checks params for transfer + * @param party Party params to check + */ + function hasValidParams(Party calldata party) external pure returns (bool) { + return (party.amount != 0); + } + /** * @notice Function to wrap safeTransferFrom for ERC1155 * @param from address Wallet address to transfer from @@ -46,6 +54,7 @@ contract ERC1155Adapter is IAdapter { uint256 id, address token ) external { + if (amount == 0) revert AmountOrIDInvalid("amount"); IERC1155(token).safeTransferFrom(from, to, id, amount, "0x00"); } } diff --git a/source/swap/contracts/adapters/ERC20Adapter.sol b/source/swap/contracts/adapters/ERC20Adapter.sol index 0c847f6cf..0af08fcaa 100644 --- a/source/swap/contracts/adapters/ERC20Adapter.sol +++ b/source/swap/contracts/adapters/ERC20Adapter.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.17; +pragma solidity 0.8.23; import "../interfaces/IAdapter.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; @@ -14,8 +14,8 @@ contract ERC20Adapter is IAdapter { bytes4 public constant interfaceId = 0x36372b07; /** - * @notice Function to wrap token transfer for different token types - * @param party Party from whom swap would be made + * @notice Checks allowance on an ERC20 + * @param party Party params to check * @dev Use call: "msg.sender" is Swap contract */ function hasAllowance(Party calldata party) external view returns (bool) { @@ -25,13 +25,21 @@ contract ERC20Adapter is IAdapter { } /** - * @notice Function to wrap token transfer for different token types - * @param party Party from whom swap would be made + * @notice Checks balance on an ERC20 + * @param party Party params to check */ function hasBalance(Party calldata party) external view returns (bool) { return IERC20(party.token).balanceOf(party.wallet) >= party.amount; } + /** + * @notice Checks params for transfer + * @param party Party params to check + */ + function hasValidParams(Party calldata party) external pure returns (bool) { + return (party.id == 0); + } + /** * @notice Function to wrap safeTransferFrom for ERC20 * @param from address Wallet address to transfer from @@ -48,7 +56,7 @@ contract ERC20Adapter is IAdapter { uint256 id, address token ) external { - if (id != 0) revert InvalidArgument("id"); + if (id != 0) revert AmountOrIDInvalid("id"); IERC20(token).safeTransferFrom(from, to, amount); } } diff --git a/source/swap/contracts/adapters/ERC721Adapter.sol b/source/swap/contracts/adapters/ERC721Adapter.sol index 8d5257216..3d05926f5 100644 --- a/source/swap/contracts/adapters/ERC721Adapter.sol +++ b/source/swap/contracts/adapters/ERC721Adapter.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.17; +pragma solidity 0.8.23; import "../interfaces/IAdapter.sol"; import "@openzeppelin/contracts/token/ERC721/IERC721.sol"; @@ -12,8 +12,8 @@ contract ERC721Adapter is IAdapter { bytes4 public constant interfaceId = 0x80ac58cd; /** - * @notice Function to wrap token transfer for different token types - * @param party Party from whom swap would be made + * @notice Checks allowance on an ERC721 + * @param party Party params to check * @dev Use call: "msg.sender" is Swap contract */ function hasAllowance(Party calldata party) external view returns (bool) { @@ -21,13 +21,21 @@ contract ERC721Adapter is IAdapter { } /** - * @notice Function to wrap token transfer for different token types - * @param party Party from whom swap would be made + * @notice Checks balance on an ERC721 + * @param party Party params to check */ function hasBalance(Party calldata party) external view returns (bool) { return IERC721(party.token).ownerOf(party.id) == party.wallet; } + /** + * @notice Checks params for transfer + * @param party Party params to check + */ + function hasValidParams(Party calldata party) external pure returns (bool) { + return (party.amount == 0); + } + /** * @notice Function to wrap safeTransferFrom for ERC721 * @param from address Wallet address to transfer from @@ -44,7 +52,7 @@ contract ERC721Adapter is IAdapter { uint256 id, address token ) external { - if (amount != 0) revert InvalidArgument("amount"); + if (amount != 0) revert AmountOrIDInvalid("amount"); IERC721(token).safeTransferFrom(from, to, id); } } diff --git a/source/swap/contracts/interfaces/IAdapter.sol b/source/swap/contracts/interfaces/IAdapter.sol index 178e8f566..2b2067abf 100644 --- a/source/swap/contracts/interfaces/IAdapter.sol +++ b/source/swap/contracts/interfaces/IAdapter.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.17; +pragma solidity 0.8.23; struct Party { address wallet; // Wallet address of the party @@ -17,7 +17,7 @@ interface IAdapter { /** * @notice Revert if provided an invalid transfer argument */ - error InvalidArgument(string); + error AmountOrIDInvalid(string); /** * @notice Return the ERC165 interfaceId this adapter supports @@ -25,17 +25,23 @@ interface IAdapter { function interfaceId() external view returns (bytes4); /** - * @notice Function to wrap token transfer for different token types - * @param party Party from whom swap would be made + * @notice Checks allowance on a token + * @param party Party params to check */ function hasAllowance(Party calldata party) external view returns (bool); /** - * @notice Function to wrap token transfer for different token types - * @param party Party from whom swap would be made + * @notice Checks balance on a token + * @param party Party params to check */ function hasBalance(Party calldata party) external view returns (bool); + /** + * @notice Checks params for transfer + * @param party Party params to check + */ + function hasValidParams(Party calldata party) external view returns (bool); + /** * @notice Function to wrap token transfer for different token types * @param from address Wallet address to transfer from diff --git a/source/swap/contracts/interfaces/ISwap.sol b/source/swap/contracts/interfaces/ISwap.sol index 190223a44..6c67b8c63 100644 --- a/source/swap/contracts/interfaces/ISwap.sol +++ b/source/swap/contracts/interfaces/ISwap.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.17; +pragma solidity 0.8.23; import "./IAdapter.sol"; @@ -65,6 +65,11 @@ interface ISwap { function cancelUpTo(uint256 minimumNonce) external; + function check( + address, + Order calldata + ) external view returns (bytes32[] memory, uint256); + function nonceUsed(address, uint256) external view returns (bool); function authorize(address sender) external; diff --git a/source/swap/contracts/test/ERC721Royalty.sol b/source/swap/contracts/test/ERC721Royalty.sol index 22d702f3a..97564c492 100644 --- a/source/swap/contracts/test/ERC721Royalty.sol +++ b/source/swap/contracts/test/ERC721Royalty.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.17; +pragma solidity 0.8.23; import "@openzeppelin/contracts/token/common/ERC2981.sol"; import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; diff --git a/source/swap/deploys-adapters-blocks.js b/source/swap/deploys-adapters-blocks.js index f2c4f0517..db72feee5 100644 --- a/source/swap/deploys-adapters-blocks.js +++ b/source/swap/deploys-adapters-blocks.js @@ -1,21 +1,4 @@ module.exports = { - 1: [18313766, 18313767, 18313768], - 5: [9836731, 9836732, 9836733], - 30: [5709851, 5709853, 5709855], - 31: [4368314, 4368316, 4368318], - 40: [305711741, 305711756, 305711770], - 41: [262035901, 262035908, 262035925], - 56: [32456348, 32456350, 32456351], - 97: [34057531, 34057532, 34057534], - 137: [48518034, 48518037, 48518040], - 8453: [5043421, 5043424, 5043426], - 42161: [139082410, 139082419, 139082444], - 43113: [26625713, 26625715, 26625718], - 43114: [36240341, 36240343, 36240345], - 59140: [1688876, 1688877, 1688878], - 59144: [596955, 596956, 596957], - 80001: [41015510, 41015513, 41015516], - 84531: [10838557, 10838560, 10838563], - 421613: [46572871, 46572877, 46572894], - 11155111: [4506677, 4506684, 4506685], + 5: [10352102, 10352114, 10352115], + 11155111: [5060109, 5060110, 5060111], } diff --git a/source/swap/deploys-adapters-blocks.js.d copy.ts b/source/swap/deploys-adapters-blocks.js.d copy.ts new file mode 100644 index 000000000..0b83abdfb --- /dev/null +++ b/source/swap/deploys-adapters-blocks.js.d copy.ts @@ -0,0 +1 @@ +declare module '@airswap/swap/deploys-adapters-blocks.js' diff --git a/source/swap/deploys-adapters.js b/source/swap/deploys-adapters.js index 7a9244403..421d9d47c 100644 --- a/source/swap/deploys-adapters.js +++ b/source/swap/deploys-adapters.js @@ -1,97 +1,12 @@ module.exports = { - 1: [ - '0x31b253F33392b2e883168d080862B059b11e4f7C', - '0x541941015dCdc748E06fb385a1900Eb1DB5721fA', - '0x6f3d53Cced8b88170218C421B603EA76097caBeF', - ], 5: [ - '0x31b253F33392b2e883168d080862B059b11e4f7C', - '0x541941015dCdc748E06fb385a1900Eb1DB5721fA', - '0x6f3d53Cced8b88170218C421B603EA76097caBeF', - ], - 30: [ - '0x31b253F33392b2e883168d080862B059b11e4f7C', - '0x541941015dCdc748E06fb385a1900Eb1DB5721fA', - '0x6f3d53Cced8b88170218C421B603EA76097caBeF', - ], - 31: [ - '0x31b253F33392b2e883168d080862B059b11e4f7C', - '0x541941015dCdc748E06fb385a1900Eb1DB5721fA', - '0x6f3d53Cced8b88170218C421B603EA76097caBeF', - ], - 40: [ - '0x31b253F33392b2e883168d080862B059b11e4f7C', - '0x541941015dCdc748E06fb385a1900Eb1DB5721fA', - '0x6f3d53Cced8b88170218C421B603EA76097caBeF', - ], - 41: [ - '0x31b253F33392b2e883168d080862B059b11e4f7C', - '0x541941015dCdc748E06fb385a1900Eb1DB5721fA', - '0x6f3d53Cced8b88170218C421B603EA76097caBeF', - ], - 56: [ - '0x31b253F33392b2e883168d080862B059b11e4f7C', - '0x541941015dCdc748E06fb385a1900Eb1DB5721fA', - '0x6f3d53Cced8b88170218C421B603EA76097caBeF', - ], - 97: [ - '0x31b253F33392b2e883168d080862B059b11e4f7C', - '0x541941015dCdc748E06fb385a1900Eb1DB5721fA', - '0x6f3d53Cced8b88170218C421B603EA76097caBeF', - ], - 137: [ - '0x31b253F33392b2e883168d080862B059b11e4f7C', - '0x541941015dCdc748E06fb385a1900Eb1DB5721fA', - '0x6f3d53Cced8b88170218C421B603EA76097caBeF', - ], - 8453: [ - '0x31b253F33392b2e883168d080862B059b11e4f7C', - '0x541941015dCdc748E06fb385a1900Eb1DB5721fA', - '0x6f3d53Cced8b88170218C421B603EA76097caBeF', - ], - 42161: [ - '0x31b253F33392b2e883168d080862B059b11e4f7C', - '0x541941015dCdc748E06fb385a1900Eb1DB5721fA', - '0x6f3d53Cced8b88170218C421B603EA76097caBeF', - ], - 43113: [ - '0x31b253F33392b2e883168d080862B059b11e4f7C', - '0x541941015dCdc748E06fb385a1900Eb1DB5721fA', - '0x6f3d53Cced8b88170218C421B603EA76097caBeF', - ], - 43114: [ - '0x31b253F33392b2e883168d080862B059b11e4f7C', - '0x541941015dCdc748E06fb385a1900Eb1DB5721fA', - '0x6f3d53Cced8b88170218C421B603EA76097caBeF', - ], - 59140: [ - '0x31b253F33392b2e883168d080862B059b11e4f7C', - '0x541941015dCdc748E06fb385a1900Eb1DB5721fA', - '0x6f3d53Cced8b88170218C421B603EA76097caBeF', - ], - 59144: [ - '0x31b253F33392b2e883168d080862B059b11e4f7C', - '0x541941015dCdc748E06fb385a1900Eb1DB5721fA', - '0x6f3d53Cced8b88170218C421B603EA76097caBeF', - ], - 80001: [ - '0x31b253F33392b2e883168d080862B059b11e4f7C', - '0x541941015dCdc748E06fb385a1900Eb1DB5721fA', - '0x6f3d53Cced8b88170218C421B603EA76097caBeF', - ], - 84531: [ - '0x31b253F33392b2e883168d080862B059b11e4f7C', - '0x541941015dCdc748E06fb385a1900Eb1DB5721fA', - '0x6f3d53Cced8b88170218C421B603EA76097caBeF', - ], - 421613: [ - '0x31b253F33392b2e883168d080862B059b11e4f7C', - '0x541941015dCdc748E06fb385a1900Eb1DB5721fA', - '0x6f3d53Cced8b88170218C421B603EA76097caBeF', + '0x49842b86486ddbb862f5b6c18617faa866399b4f', + '0x942f3f88d1B1dC9566e45b57D4453F56B25a34fC', + '0xc0799BA9b7bdBA773F77943a9FD448d188345081', ], 11155111: [ - '0x31b253F33392b2e883168d080862B059b11e4f7C', - '0x541941015dCdc748E06fb385a1900Eb1DB5721fA', - '0x6f3d53Cced8b88170218C421B603EA76097caBeF', + '0x49842b86486ddBb862f5b6C18617faA866399B4f', + '0x942f3f88d1B1dC9566e45b57D4453F56B25a34fC', + '0xc0799BA9b7bdBA773F77943a9FD448d188345081', ], } diff --git a/source/swap/deploys-adapters.js.d.ts b/source/swap/deploys-adapters.js.d.ts new file mode 100644 index 000000000..58162b42b --- /dev/null +++ b/source/swap/deploys-adapters.js.d.ts @@ -0,0 +1 @@ +declare module '@airswap/swap/deploys-adapters.js' diff --git a/source/swap/deploys-blocks.js b/source/swap/deploys-blocks.js index d61f21ab9..acd9bc3bb 100644 --- a/source/swap/deploys-blocks.js +++ b/source/swap/deploys-blocks.js @@ -1,21 +1,4 @@ module.exports = { - 1: 18313778, - 5: 9836886, - 30: 5709864, - 31: 4368354, - 40: 305712061, - 41: 262036091, - 56: 32456378, - 97: 34057567, - 137: 48518069, - 8453: 5043477, - 42161: 139082902, - 43113: 26625796, - 43114: 36240382, - 59140: 1688885, - 59144: 596964, - 80001: 41015536, - 84531: 10838592, - 421613: 46573093, - 11155111: 4508673, + 5: 10352126, + 11155111: 5060116, } diff --git a/source/swap/deploys-blocks.js.d.ts b/source/swap/deploys-blocks.js.d.ts new file mode 100644 index 000000000..9d2baa1b8 --- /dev/null +++ b/source/swap/deploys-blocks.js.d.ts @@ -0,0 +1 @@ +declare module '@airswap/swap/deploys-blocks.js' diff --git a/source/swap/deploys.js b/source/swap/deploys.js index ac9f1a4fa..ecfd9ac5b 100644 --- a/source/swap/deploys.js +++ b/source/swap/deploys.js @@ -1,21 +1,4 @@ module.exports = { - 1: '0xb926D88D6BdD560383fCd6537bbf5Aa863470318', - 5: '0xb926D88D6BdD560383fCd6537bbf5Aa863470318', - 30: '0xb926D88D6BdD560383fCd6537bbf5Aa863470318', - 31: '0xb926D88D6BdD560383fCd6537bbf5Aa863470318', - 40: '0xb926D88D6BdD560383fCd6537bbf5Aa863470318', - 41: '0xb926D88D6BdD560383fCd6537bbf5Aa863470318', - 56: '0xb926D88D6BdD560383fCd6537bbf5Aa863470318', - 97: '0xb926D88D6BdD560383fCd6537bbf5Aa863470318', - 137: '0xb926D88D6BdD560383fCd6537bbf5Aa863470318', - 8453: '0xb926D88D6BdD560383fCd6537bbf5Aa863470318', - 42161: '0xb926D88D6BdD560383fCd6537bbf5Aa863470318', - 43113: '0xb926D88D6BdD560383fCd6537bbf5Aa863470318', - 43114: '0xb926D88D6BdD560383fCd6537bbf5Aa863470318', - 59140: '0xb926D88D6BdD560383fCd6537bbf5Aa863470318', - 59144: '0xb926D88D6BdD560383fCd6537bbf5Aa863470318', - 80001: '0xb926D88D6BdD560383fCd6537bbf5Aa863470318', - 84531: '0xb926D88D6BdD560383fCd6537bbf5Aa863470318', - 421613: '0xb926D88D6BdD560383fCd6537bbf5Aa863470318', - 11155111: '0xb926D88D6BdD560383fCd6537bbf5Aa863470318', + 5: '0x04a885E71F1E04b7493F8cfC02c565944707710A', + 11155111: '0x04a885E71F1E04b7493F8cfC02c565944707710A', } diff --git a/source/swap/deploys.js.d.ts b/source/swap/deploys.js.d.ts index 180b656b5..a3d7be66b 100644 --- a/source/swap/deploys.js.d.ts +++ b/source/swap/deploys.js.d.ts @@ -1,4 +1 @@ declare module '@airswap/swap/deploys.js' -declare module '@airswap/swap/deploys-adapters.js' -declare module '@airswap/swap/deploys-blocks.js' -declare module '@airswap/swap/deploys-adapters-blocks.js' diff --git a/source/swap/package.json b/source/swap/package.json index 53df5f677..2176f23c3 100644 --- a/source/swap/package.json +++ b/source/swap/package.json @@ -1,6 +1,6 @@ { "name": "@airswap/swap", - "version": "4.1.2", + "version": "4.1.3-beta.0", "description": "AirSwap: Atomic Token Swap", "license": "MIT", "repository": { @@ -32,7 +32,7 @@ "@openzeppelin/contracts": "^4.8.3" }, "devDependencies": { - "@airswap/constants": "4.1.8", + "@airswap/constants": "4.1.9-beta.0", "@airswap/types": "4.1.3", "@airswap/utils": "4.1.12", "@nomicfoundation/hardhat-network-helpers": "^1.0.7" diff --git a/source/swap/scripts/config.js b/source/swap/scripts/config.js new file mode 100644 index 000000000..f6a4c3ec5 --- /dev/null +++ b/source/swap/scripts/config.js @@ -0,0 +1,8 @@ +const { ChainIds, TokenKinds } = require('@airswap/constants') + +module.exports = { + [ChainIds.MAINNET]: { + requiredSenderKind: TokenKinds.ERC20, + protocolFee: 7, + }, +} diff --git a/source/swap/scripts/deploy-adapters.js b/source/swap/scripts/deploy-adapters.js index eef43f8ea..d46b476fc 100644 --- a/source/swap/scripts/deploy-adapters.js +++ b/source/swap/scripts/deploy-adapters.js @@ -10,7 +10,7 @@ const adapterBlocks = require('../deploys-adapters-blocks.js') async function main() { await run('compile') - const config = await prettier.resolveConfig('../deploys.js') + const prettierConfig = await prettier.resolveConfig('../deploys.js') const [deployer] = await ethers.getSigners() const gasPrice = await deployer.getGasPrice() @@ -50,7 +50,7 @@ async function main() { './deploys-adapters.js', prettier.format( `module.exports = ${JSON.stringify(adapterDeploys, null, '\t')}`, - { ...config, parser: 'babel' } + { ...prettierConfig, parser: 'babel' } ) ) adapterBlocks[chainId] = blocks @@ -58,7 +58,7 @@ async function main() { './deploys-adapters-blocks.js', prettier.format( `module.exports = ${JSON.stringify(adapterBlocks, null, '\t')}`, - { ...config, parser: 'babel' } + { ...prettierConfig, parser: 'babel' } ) ) diff --git a/source/swap/scripts/deploy.js b/source/swap/scripts/deploy.js index a0c73a2d8..c3a1407e8 100644 --- a/source/swap/scripts/deploy.js +++ b/source/swap/scripts/deploy.js @@ -7,7 +7,6 @@ const { chainNames, chainLabels, ChainIds, - TokenKinds, protocolFeeReceiverAddresses, ADDRESS_ZERO, } = require('@airswap/constants') @@ -16,10 +15,11 @@ const poolDeploys = require('@airswap/pool/deploys.js') const swapDeploys = require('../deploys.js') const swapBlocks = require('../deploys-blocks.js') const adapterDeploys = require('../deploys-adapters.js') +const config = require('./config.js') async function main() { await run('compile') - const config = await prettier.resolveConfig('../deploys.js') + const prettierConfig = await prettier.resolveConfig('../deploys.js') const [deployer] = await ethers.getSigners() const gasPrice = await deployer.getGasPrice() @@ -28,22 +28,28 @@ async function main() { console.log('Value for --network flag is required') return } + if (!adapterDeploys[chainId]) { + console.log('Adapters must be deployed first.') + return + } + console.log(`Deployer: ${deployer.address}`) console.log(`Network: ${chainNames[chainId].toUpperCase()}`) console.log(`Gas price: ${gasPrice / 10 ** 9} gwei\n`) - const requiredSenderKind = TokenKinds.ERC20 - const protocolFee = 7 + let requiredSenderKind + let protocolFee + if (config[chainId]) { + ;({ requiredSenderKind, protocolFee } = config[chainId]) + } else { + ;({ requiredSenderKind, protocolFee } = config[ChainIds.MAINNET]) + } + let protocolFeeReceiver = poolDeploys[chainId] || ADDRESS_ZERO if (protocolFeeReceiverAddresses[chainId]) { protocolFeeReceiver = protocolFeeReceiverAddresses[chainId] } - if (!adapterDeploys[chainId]) { - console.log('Adapters must be deployed first.') - return - } - console.log(`\nadapters: ${JSON.stringify(adapterDeploys[chainId])}`) console.log(`requiredSenderKind: ${requiredSenderKind}`) console.log(`protocolFee: ${protocolFee}`) @@ -72,7 +78,7 @@ async function main() { './deploys.js', prettier.format( `module.exports = ${JSON.stringify(swapDeploys, null, '\t')}`, - { ...config, parser: 'babel' } + { ...prettierConfig, parser: 'babel' } ) ) swapBlocks[chainId] = ( @@ -82,7 +88,7 @@ async function main() { './deploys-blocks.js', prettier.format( `module.exports = ${JSON.stringify(swapBlocks, null, '\t')}`, - { ...config, parser: 'babel' } + { ...prettierConfig, parser: 'babel' } ) ) console.log(`Deployed: ${swapDeploys[chainId]} @ ${swapBlocks[chainId]}`) diff --git a/source/swap/scripts/verify.js b/source/swap/scripts/verify.js index 64462f243..e446a2eac 100644 --- a/source/swap/scripts/verify.js +++ b/source/swap/scripts/verify.js @@ -2,12 +2,13 @@ const { ethers, run } = require('hardhat') const poolDeploys = require('@airswap/pool/deploys.js') const { + ChainIds, chainNames, - TokenKinds, protocolFeeReceiverAddresses, } = require('@airswap/constants') const swapDeploys = require('../deploys.js') const adapterDeploys = require('../deploys-adapters.js') +const config = require('./config.js') async function main() { await run('compile') @@ -16,8 +17,14 @@ async function main() { const chainId = await deployer.getChainId() - const requiredSenderKind = TokenKinds.ERC20 - const protocolFee = 7 + let requiredSenderKind + let protocolFee + if (config[chainId]) { + ;({ requiredSenderKind, protocolFee } = config[chainId]) + } else { + ;({ requiredSenderKind, protocolFee } = config[ChainIds.MAINNET]) + } + let protocolFeeReceiver = poolDeploys[chainId] if (protocolFeeReceiverAddresses[chainId]) { protocolFeeReceiver = protocolFeeReceiverAddresses[chainId] diff --git a/source/swap/test/ERC1155Adapter.js b/source/swap/test/ERC1155Adapter.js index 909c5a64e..0cab0f356 100644 --- a/source/swap/test/ERC1155Adapter.js +++ b/source/swap/test/ERC1155Adapter.js @@ -54,7 +54,9 @@ describe('ERC1155Adapter Unit', () => { }) it('transfer succeeds', async () => { - await token.mock.safeTransferFrom.returns() + await token.mock[ + 'safeTransferFrom(address,address,uint256,uint256,bytes)' + ].returns() await expect( adapter .connect(anyone) @@ -67,4 +69,17 @@ describe('ERC1155Adapter Unit', () => { ) ).to.not.be.reverted }) + + it('transfer with zero amount fails', async () => { + await token.mock[ + 'safeTransferFrom(address,address,uint256,uint256,bytes)' + ].returns() + await expect( + adapter + .connect(anyone) + .transfer(party.wallet, anyone.address, '0', party.id, party.token) + ) + .to.be.revertedWith('AmountOrIDInvalid') + .withArgs('amount') + }) }) diff --git a/source/swap/test/ERC20Adapter.js b/source/swap/test/ERC20Adapter.js index 300a156a1..9d37547df 100644 --- a/source/swap/test/ERC20Adapter.js +++ b/source/swap/test/ERC20Adapter.js @@ -75,7 +75,7 @@ describe('ERC20Adapter Unit', () => { .connect(anyone) .transfer(party.wallet, anyone.address, party.amount, '1', party.token) ) - .to.be.revertedWith('InvalidArgument') + .to.be.revertedWith('AmountOrIDInvalid') .withArgs('id') }) }) diff --git a/source/swap/test/ERC721Adapter.js b/source/swap/test/ERC721Adapter.js index be17b4845..8424c545b 100644 --- a/source/swap/test/ERC721Adapter.js +++ b/source/swap/test/ERC721Adapter.js @@ -68,7 +68,7 @@ describe('ERC721Adapter Unit', () => { .connect(anyone) .transfer(party.wallet, anyone.address, '1', party.id, party.token) ) - .to.be.revertedWith('InvalidArgument') + .to.be.revertedWith('AmountOrIDInvalid') .withArgs('amount') }) }) diff --git a/source/swap/test/Swap.js b/source/swap/test/Swap.js index 12c3b942f..7f5073ca4 100644 --- a/source/swap/test/Swap.js +++ b/source/swap/test/Swap.js @@ -4,6 +4,7 @@ const { ethers, waffle } = require('hardhat') const { deployMockContract } = waffle const IERC20 = require('@openzeppelin/contracts/build/contracts/IERC20.json') const IERC721 = require('@openzeppelin/contracts/build/contracts/ERC721Royalty.json') +const IERC1155 = require('@openzeppelin/contracts/build/contracts/IERC1155.json') const { createOrder, createOrderSignature } = require('@airswap/utils') const { TokenKinds, ADDRESS_ZERO } = require('@airswap/constants') @@ -25,6 +26,8 @@ let erc20token let erc20adapter let erc721token let erc721adapter +let erc1155token +let erc1155adapter let swap async function signOrder(order, wallet, swapContract) { @@ -78,8 +81,9 @@ describe('Swap Unit', () => { await ethers.getContractFactory('ERC20Adapter') ).deploy() await erc20adapter.deployed() + erc721token = await deployMockContract(deployer, IERC721.abi) - await erc721token.mock.isApprovedForAll.returns(true) + await erc721token.mock.getApproved.returns(sender.address) await erc721token.mock.ownerOf.returns(sender.address) await erc721token.mock[ 'safeTransferFrom(address,address,uint256)' @@ -88,10 +92,22 @@ describe('Swap Unit', () => { await ethers.getContractFactory('ERC721Adapter') ).deploy() await erc721adapter.deployed() + + erc1155token = await deployMockContract(deployer, IERC1155.abi) + await erc1155token.mock.isApprovedForAll.returns(true) + await erc1155token.mock.balanceOf.returns(DEFAULT_AMOUNT) + await erc1155token.mock[ + 'safeTransferFrom(address,address,uint256,uint256,bytes)' + ].returns() + erc1155adapter = await ( + await ethers.getContractFactory('ERC1155Adapter') + ).deploy() + await erc1155adapter.deployed() + swap = await ( await ethers.getContractFactory('Swap') ).deploy( - [erc20adapter.address, erc721adapter.address], + [erc20adapter.address, erc721adapter.address, erc1155adapter.address], TokenKinds.ERC20, PROTOCOL_FEE, protocolFeeWallet.address @@ -590,6 +606,56 @@ describe('Swap Unit', () => { expect(errors[1]).to.equal(0) }) + it('check with invalid erc20 params fails', async () => { + const order = await createSignedOrder( + { + signer: { + kind: TokenKinds.ERC20, + id: '1', + }, + }, + signer + ) + const [errors] = await swap.check(sender.address, order) + expect(errors[0]).to.be.equal( + ethers.utils.formatBytes32String('AmountOrIDInvalid') + ) + }) + + it('check with invalid erc721 params fails', async () => { + const order = await createSignedOrder( + { + signer: { + kind: TokenKinds.ERC721, + token: erc721token.address, + amount: '1', + }, + }, + signer + ) + const [errors] = await swap.check(sender.address, order) + expect(errors[2]).to.be.equal( + ethers.utils.formatBytes32String('AmountOrIDInvalid') + ) + }) + + it('check with invalid erc1155 params fails', async () => { + const order = await createSignedOrder( + { + signer: { + kind: TokenKinds.ERC1155, + token: erc1155token.address, + amount: '0', + }, + }, + signer + ) + const [errors] = await swap.check(sender.address, order) + expect(errors[0]).to.be.equal( + ethers.utils.formatBytes32String('AmountOrIDInvalid') + ) + }) + it('check without allowances or balances fails', async () => { await erc20token.mock.allowance.returns('0') await erc20token.mock.balanceOf.returns('0') diff --git a/source/wrapper/contracts/Wrapper.sol b/source/wrapper/contracts/Wrapper.sol index 09fa3da0a..677c20e65 100644 --- a/source/wrapper/contracts/Wrapper.sol +++ b/source/wrapper/contracts/Wrapper.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; +pragma solidity 0.8.23; import "@airswap/swap-erc20/contracts/interfaces/ISwapERC20.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; diff --git a/source/wrapper/deploys-blocks-weth.js.d.ts b/source/wrapper/deploys-blocks-weth.js.d.ts new file mode 100644 index 000000000..213db0e71 --- /dev/null +++ b/source/wrapper/deploys-blocks-weth.js.d.ts @@ -0,0 +1 @@ +declare module '@airswap/wrapper/deploys-blocks-weth.js' diff --git a/source/wrapper/deploys-blocks.js.d.ts b/source/wrapper/deploys-blocks.js.d.ts new file mode 100644 index 000000000..8b33d7d2d --- /dev/null +++ b/source/wrapper/deploys-blocks.js.d.ts @@ -0,0 +1 @@ +declare module '@airswap/wrapper/deploys-blocks.js' diff --git a/source/wrapper/deploys-weth.js.d.ts b/source/wrapper/deploys-weth.js.d.ts new file mode 100644 index 000000000..ba4b1b4d2 --- /dev/null +++ b/source/wrapper/deploys-weth.js.d.ts @@ -0,0 +1 @@ +declare module '@airswap/wrapper/deploys-weth.js' diff --git a/source/wrapper/deploys.js.d.ts b/source/wrapper/deploys.js.d.ts index 14a5d1837..2411fe230 100644 --- a/source/wrapper/deploys.js.d.ts +++ b/source/wrapper/deploys.js.d.ts @@ -1,4 +1 @@ declare module '@airswap/wrapper/deploys.js' -declare module '@airswap/wrapper/deploys-weth.js' -declare module '@airswap/wrapper/deploys-blocks.js' -declare module '@airswap/wrapper/deploys-blocks-weth.js' diff --git a/source/wrapper/package.json b/source/wrapper/package.json index 89ffd21cd..ee92d9945 100644 --- a/source/wrapper/package.json +++ b/source/wrapper/package.json @@ -1,6 +1,6 @@ { "name": "@airswap/wrapper", - "version": "4.1.5", + "version": "4.1.6-beta.0", "description": "AirSwap: Wrap and Unwrap Native Tokens", "license": "MIT", "repository": { @@ -28,11 +28,11 @@ "owners": "hardhat run ./scripts/owner.js" }, "dependencies": { - "@airswap/swap-erc20": "4.1.6", + "@airswap/swap-erc20": "4.1.7-beta.0", "@openzeppelin/contracts": "^4.8.3" }, "devDependencies": { - "@airswap/constants": "4.1.8", + "@airswap/constants": "4.1.9-beta.0", "@airswap/utils": "4.1.12", "@airswap/types": "4.1.3", "@uniswap/v2-periphery": "^1.1.0-beta.0", diff --git a/source/wrapper/scripts/deploy.js b/source/wrapper/scripts/deploy.js index f8c917093..9ec6d9954 100644 --- a/source/wrapper/scripts/deploy.js +++ b/source/wrapper/scripts/deploy.js @@ -12,7 +12,7 @@ const { getReceiptUrl } = require('@airswap/utils') async function main() { await run('compile') - const config = await prettier.resolveConfig('../deploys.js') + const prettierConfig = await prettier.resolveConfig('../deploys.js') const [deployer] = await ethers.getSigners() const gasPrice = await deployer.getGasPrice() @@ -57,7 +57,7 @@ async function main() { './deploys.js', prettier.format( `module.exports = ${JSON.stringify(wrapperDeploys, null, '\t')}`, - { ...config, parser: 'babel' } + { ...prettierConfig, parser: 'babel' } ) ) wrapperBlocks[chainId] = ( @@ -67,7 +67,7 @@ async function main() { './deploys-blocks.js', prettier.format( `module.exports = ${JSON.stringify(wrapperBlocks, null, '\t')}`, - { ...config, parser: 'babel' } + { ...prettierConfig, parser: 'babel' } ) ) console.log( diff --git a/source/wrapper/test/Wrapper.js b/source/wrapper/test/Wrapper.js index 31730b437..957e94fa6 100644 --- a/source/wrapper/test/Wrapper.js +++ b/source/wrapper/test/Wrapper.js @@ -31,8 +31,8 @@ describe('Wrapper Unit Tests', () => { const PROTOCOL_FEE = '30' const PROTOCOL_FEE_LIGHT = '7' const DEFAULT_AMOUNT = '10000' - const REBATE_SCALE = '10' - const REBATE_MAX = '100' + const BONUS_SCALE = '10' + const BONUS_MAX = '100' async function createSignedOrderERC20(params, signer) { const unsignedOrder = createOrderERC20({ @@ -93,8 +93,8 @@ describe('Wrapper Unit Tests', () => { PROTOCOL_FEE, PROTOCOL_FEE_LIGHT, protocolFeeWallet.address, - REBATE_SCALE, - REBATE_MAX + BONUS_SCALE, + BONUS_MAX ) await swapERC20.deployed() diff --git a/tools/constants/index.ts b/tools/constants/index.ts index 239ea7cb3..0684f6e37 100644 --- a/tools/constants/index.ts +++ b/tools/constants/index.ts @@ -203,8 +203,8 @@ export const explorerApiUrls: Record = { export const stakingTokenAddresses: Record = { [ChainIds.MAINNET]: '0x27054b13b1b798b345b591a4d22e6562d47ea75a', - [ChainIds.GOERLI]: '0x7eef7238fd4f65312a53c5d195e675068afbb1d0', - [ChainIds.SEPOLIA]: '0x5e5a433cdfb14ab228c45e23251ad83f7b1e3302', + [ChainIds.GOERLI]: '0x23474e94e27ac59eec4411ce96c322add8833680', + [ChainIds.SEPOLIA]: '0x517d482f686f11b922eed764692f2b42663ce2fa', } export const ownerAddresses: Record = { diff --git a/tools/constants/package.json b/tools/constants/package.json index 380a4c9d6..1340b6cfb 100644 --- a/tools/constants/package.json +++ b/tools/constants/package.json @@ -1,6 +1,6 @@ { "name": "@airswap/constants", - "version": "4.1.8", + "version": "4.1.9-beta.0", "description": "AirSwap: Constants for Developers", "repository": { "type": "git", diff --git a/tools/libraries/package.json b/tools/libraries/package.json index 6c5e8fcb6..7da54717d 100644 --- a/tools/libraries/package.json +++ b/tools/libraries/package.json @@ -1,6 +1,6 @@ { "name": "@airswap/libraries", - "version": "4.1.17", + "version": "4.1.19-beta.0", "description": "AirSwap: Libraries for Developers", "repository": { "type": "git", @@ -26,17 +26,17 @@ "test:ci": "yarn test" }, "dependencies": { - "@airswap/balances": "4.0.4", - "@airswap/constants": "4.1.8", + "@airswap/batch-call": "4.1.0-beta.0", + "@airswap/constants": "4.1.9-beta.0", "@airswap/jsonrpc-client-websocket": "0.0.1", "@airswap/registry": "4.1.3", "@airswap/pool": "4.1.4", - "@airswap/staking": "4.0.5", - "@airswap/swap": "4.1.2", - "@airswap/swap-erc20": "4.1.6", + "@airswap/staking": "4.1.0-beta.0", + "@airswap/swap": "4.1.3-beta.0", + "@airswap/swap-erc20": "4.1.7-beta.0", "@airswap/types": "4.1.3", "@airswap/utils": "4.1.12", - "@airswap/wrapper": "4.1.5", + "@airswap/wrapper": "4.1.6-beta.0", "browser-or-node": "^2.1.1", "ethers": "^5.6.9", "jayson": "^4.0.0", diff --git a/tools/libraries/src/Contracts.ts b/tools/libraries/src/Contracts.ts index 042f62ca2..1dae7c96c 100644 --- a/tools/libraries/src/Contracts.ts +++ b/tools/libraries/src/Contracts.ts @@ -20,10 +20,10 @@ import swapERC20Blocks from '@airswap/swap-erc20/deploys-blocks.js' import wrapperBlocks from '@airswap/wrapper/deploys-blocks.js' import wethBlocks from '@airswap/wrapper/deploys-blocks-weth.js' -import BalanceChecker from '@airswap/balances/build/contracts/BalanceChecker.sol/BalanceChecker.json' -import balancesDeploys from '@airswap/balances/deploys.js' -const balancesInterface = new ethers.utils.Interface( - JSON.stringify(BalanceChecker.abi) +import BatchCallContract from '@airswap/batch-call/build/contracts/BatchCall.sol/BatchCall.json' +import batchCallDeploys from '@airswap/batch-call/deploys.js' +const batchInterface = new ethers.utils.Interface( + JSON.stringify(BatchCallContract.abi) ) export class Contract { @@ -82,14 +82,14 @@ export const WETH = new Contract( wethBlocks, WETH9__factory ) -export const Balances = new Contract('Balances', balancesDeploys) -Balances.getContract = ( +export const BatchCall = new Contract('BatchCall', batchCallDeploys) +BatchCall.getContract = ( providerOrSigner: ethers.providers.Provider | ethers.Signer, chainId: number ): ethers.Contract => { return new ethers.Contract( - balancesDeploys[chainId], - balancesInterface, + batchCallDeploys[chainId], + batchInterface, providerOrSigner ) } diff --git a/tools/libraries/test/Server.test.ts b/tools/libraries/test/Server.test.ts index a181e3d6d..7cde47e29 100644 --- a/tools/libraries/test/Server.test.ts +++ b/tools/libraries/test/Server.test.ts @@ -91,9 +91,9 @@ function mockHttpServer(api) { order, wallet.privateKey, params.swapContract, - ChainIds.MAINNET + ChainIds.SEPOLIA )), - chainId: ChainIds.MAINNET, + chainId: ChainIds.SEPOLIA, swapContract: params.swapContract, } break @@ -108,9 +108,9 @@ function mockHttpServer(api) { order, wallet.privateKey, ADDRESS_ZERO, - ChainIds.MAINNET + ChainIds.SEPOLIA )), - chainId: ChainIds.MAINNET, + chainId: ChainIds.SEPOLIA, swapContract: ADDRESS_ZERO, }, }, @@ -165,7 +165,10 @@ describe('HTTPServer', () => { fancy .nock('https://' + URL, mockHttpServer) .it('Server getSignerSideOrderERC20()', async () => { - const server = await Server.at(URL) + const server = await Server.at(URL, { + swapContract: ADDRESS_ZERO, + chainId: ChainIds.SEPOLIA, + }) const order = await server.getSignerSideOrderERC20( '0', ADDRESS_ZERO, @@ -548,7 +551,7 @@ async function forgeFullOrder() { order: { ...unsignedOrder, ...signature, - chainId: ChainIds.MAINNET, + chainId: ChainIds.SEPOLIA, swapContract: ADDRESS_ZERO, }, }, diff --git a/tools/metadata/package.json b/tools/metadata/package.json index c3b903b58..2c6c65822 100644 --- a/tools/metadata/package.json +++ b/tools/metadata/package.json @@ -20,9 +20,9 @@ "test": "TS_NODE_COMPILER_OPTIONS='{\"strict\":false}' yarn mocha -r ts-node/esm test/*.ts" }, "dependencies": { - "@airswap/constants": "4.1.8", + "@airswap/constants": "4.1.9-beta.0", "@airswap/types": "4.1.3", - "@airswap/wrapper": "4.1.5", + "@airswap/wrapper": "4.1.6-beta.0", "@openzeppelin/contracts": "^4.8.3", "@uniswap/token-lists": "^1.0.0-beta.24", "ethers": "^5.6.9", diff --git a/tools/utils/package.json b/tools/utils/package.json index 0a88ae5b0..1c0307d55 100644 --- a/tools/utils/package.json +++ b/tools/utils/package.json @@ -21,7 +21,7 @@ "test:ci": "yarn test" }, "dependencies": { - "@airswap/constants": "4.1.8", + "@airswap/constants": "4.1.9-beta.0", "@airswap/types": "4.1.3", "@metamask/eth-sig-util": "^5.0.2", "bignumber.js": "^9.0.1", diff --git a/yarn.lock b/yarn.lock index 6588ce503..f82e4e808 100644 --- a/yarn.lock +++ b/yarn.lock @@ -589,9 +589,9 @@ "@ethersproject/strings" "^5.7.0" "@fastify/busboy@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@fastify/busboy/-/busboy-2.0.0.tgz#f22824caff3ae506b18207bad4126dbc6ccdb6b8" - integrity sha512-JUFJad5lv7jxj926GPgymrWQxxjPYuJNiNjNMzqT+HiuP6Vl3dk5xzG+8sTX96np0ZAluvaMzPsjhHZ5rNuNQQ== + version "2.1.0" + resolved "https://registry.yarnpkg.com/@fastify/busboy/-/busboy-2.1.0.tgz#0709e9f4cb252351c609c6e6d8d6779a8d25edff" + integrity sha512-+KpH+QxZU7O4675t3mnkQKcZZg56u+K/Ct2K+N2AZYNVK8kyeo/bI18tI8aPm3tvNNRyTWfj6s5tnGNlcbQRsA== "@ganache/ethereum-address@0.1.4": version "0.1.4" @@ -863,31 +863,31 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" -"@nomicfoundation/ethereumjs-block@5.0.0": - version "5.0.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-block/-/ethereumjs-block-5.0.0.tgz#f27a3df0a796e2af7df4bd226d14748c303d105b" - integrity sha512-DfhVbqM5DjriguuSv6r3TgOpyXC76oX8D/VEODsSwJQ1bZGqu4xLLfYPPTacpCAYOnewzJsZli+Ao9TBTAo2uw== - dependencies: - "@nomicfoundation/ethereumjs-common" "4.0.0" - "@nomicfoundation/ethereumjs-rlp" "5.0.0" - "@nomicfoundation/ethereumjs-trie" "6.0.0" - "@nomicfoundation/ethereumjs-tx" "5.0.0" - "@nomicfoundation/ethereumjs-util" "9.0.0" +"@nomicfoundation/ethereumjs-block@5.0.2": + version "5.0.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-block/-/ethereumjs-block-5.0.2.tgz#13a7968f5964f1697da941281b7f7943b0465d04" + integrity sha512-hSe6CuHI4SsSiWWjHDIzWhSiAVpzMUcDRpWYzN0T9l8/Rz7xNn3elwVOJ/tAyS0LqL6vitUD78Uk7lQDXZun7Q== + dependencies: + "@nomicfoundation/ethereumjs-common" "4.0.2" + "@nomicfoundation/ethereumjs-rlp" "5.0.2" + "@nomicfoundation/ethereumjs-trie" "6.0.2" + "@nomicfoundation/ethereumjs-tx" "5.0.2" + "@nomicfoundation/ethereumjs-util" "9.0.2" ethereum-cryptography "0.1.3" ethers "^5.7.1" -"@nomicfoundation/ethereumjs-blockchain@7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-blockchain/-/ethereumjs-blockchain-7.0.0.tgz#7f5aa889f96d43361aa21ec04f8dc1734e2fc818" - integrity sha512-cVRCrXZminZr0Mbx2hm0/109GZLn1v5bf0/k+SIbGn50yZm6YCdQt9CgGT0Gk56N2vy8NhXD4apo167m4LWk6Q== - dependencies: - "@nomicfoundation/ethereumjs-block" "5.0.0" - "@nomicfoundation/ethereumjs-common" "4.0.0" - "@nomicfoundation/ethereumjs-ethash" "3.0.0" - "@nomicfoundation/ethereumjs-rlp" "5.0.0" - "@nomicfoundation/ethereumjs-trie" "6.0.0" - "@nomicfoundation/ethereumjs-tx" "5.0.0" - "@nomicfoundation/ethereumjs-util" "9.0.0" +"@nomicfoundation/ethereumjs-blockchain@7.0.2": + version "7.0.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-blockchain/-/ethereumjs-blockchain-7.0.2.tgz#45323b673b3d2fab6b5008535340d1b8fea7d446" + integrity sha512-8UUsSXJs+MFfIIAKdh3cG16iNmWzWC/91P40sazNvrqhhdR/RtGDlFk2iFTGbBAZPs2+klZVzhRX8m2wvuvz3w== + dependencies: + "@nomicfoundation/ethereumjs-block" "5.0.2" + "@nomicfoundation/ethereumjs-common" "4.0.2" + "@nomicfoundation/ethereumjs-ethash" "3.0.2" + "@nomicfoundation/ethereumjs-rlp" "5.0.2" + "@nomicfoundation/ethereumjs-trie" "6.0.2" + "@nomicfoundation/ethereumjs-tx" "5.0.2" + "@nomicfoundation/ethereumjs-util" "9.0.2" abstract-level "^1.0.3" debug "^4.3.3" ethereum-cryptography "0.1.3" @@ -895,103 +895,103 @@ lru-cache "^5.1.1" memory-level "^1.0.0" -"@nomicfoundation/ethereumjs-common@4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-common/-/ethereumjs-common-4.0.0.tgz#23c97adbbb2b660da03467308821c83e314694e9" - integrity sha512-UPpm5FAGAf2B6hQ8aVgO44Rdo0k73oMMCViqNJcKMlk1s9l3rxwuPTp1l20NiGvNO2Pzqk3chFL+BzmLL2g4wQ== +"@nomicfoundation/ethereumjs-common@4.0.2": + version "4.0.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-common/-/ethereumjs-common-4.0.2.tgz#a15d1651ca36757588fdaf2a7d381a150662a3c3" + integrity sha512-I2WGP3HMGsOoycSdOTSqIaES0ughQTueOsddJ36aYVpI3SN8YSusgRFLwzDJwRFVIYDKx/iJz0sQ5kBHVgdDwg== dependencies: - "@nomicfoundation/ethereumjs-util" "9.0.0" + "@nomicfoundation/ethereumjs-util" "9.0.2" crc-32 "^1.2.0" -"@nomicfoundation/ethereumjs-ethash@3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-ethash/-/ethereumjs-ethash-3.0.0.tgz#b03586948c5bd106c230dbb1c4dc2be5740d774c" - integrity sha512-6zNv5Y3vNIsxjrsbKjMInVpo8cmR0c7yjZbBpy7NYuIMtm0JKhQoXsiFN56t/1sfn9V3v0wgrkAixo5v6bahpA== +"@nomicfoundation/ethereumjs-ethash@3.0.2": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-ethash/-/ethereumjs-ethash-3.0.2.tgz#da77147f806401ee996bfddfa6487500118addca" + integrity sha512-8PfoOQCcIcO9Pylq0Buijuq/O73tmMVURK0OqdjhwqcGHYC2PwhbajDh7GZ55ekB0Px197ajK3PQhpKoiI/UPg== dependencies: - "@nomicfoundation/ethereumjs-block" "5.0.0" - "@nomicfoundation/ethereumjs-rlp" "5.0.0" - "@nomicfoundation/ethereumjs-util" "9.0.0" + "@nomicfoundation/ethereumjs-block" "5.0.2" + "@nomicfoundation/ethereumjs-rlp" "5.0.2" + "@nomicfoundation/ethereumjs-util" "9.0.2" abstract-level "^1.0.3" bigint-crypto-utils "^3.0.23" ethereum-cryptography "0.1.3" -"@nomicfoundation/ethereumjs-evm@2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-evm/-/ethereumjs-evm-2.0.0.tgz#9023e42d0c5807720c42cf01218123c7d3a5c403" - integrity sha512-D+tr3M9sictopr3E20OVgme7YF/d0fU566WKh+ofXwmxapz/Dd8RSLSaVeKgfCI2BkzVA+XqXY08NNCV8w8fWA== +"@nomicfoundation/ethereumjs-evm@2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-evm/-/ethereumjs-evm-2.0.2.tgz#4c2f4b84c056047102a4fa41c127454e3f0cfcf6" + integrity sha512-rBLcUaUfANJxyOx9HIdMX6uXGin6lANCulIm/pjMgRqfiCRMZie3WKYxTSd8ZE/d+qT+zTedBF4+VHTdTSePmQ== dependencies: "@ethersproject/providers" "^5.7.1" - "@nomicfoundation/ethereumjs-common" "4.0.0" - "@nomicfoundation/ethereumjs-tx" "5.0.0" - "@nomicfoundation/ethereumjs-util" "9.0.0" + "@nomicfoundation/ethereumjs-common" "4.0.2" + "@nomicfoundation/ethereumjs-tx" "5.0.2" + "@nomicfoundation/ethereumjs-util" "9.0.2" debug "^4.3.3" ethereum-cryptography "0.1.3" mcl-wasm "^0.7.1" rustbn.js "~0.2.0" -"@nomicfoundation/ethereumjs-rlp@5.0.0": - version "5.0.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-rlp/-/ethereumjs-rlp-5.0.0.tgz#eececfc6b0758e0f8cf704c8128063e16d1c41cf" - integrity sha512-U1A0y330PtGb8Wft4yPVv0myWYJTesi89ItGoB0ICdqz7793KmUhpfQb2vJUXBi98wSdnxkIABO/GmsQvGKVDw== +"@nomicfoundation/ethereumjs-rlp@5.0.2": + version "5.0.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-rlp/-/ethereumjs-rlp-5.0.2.tgz#4fee8dc58a53ac6ae87fb1fca7c15dc06c6b5dea" + integrity sha512-QwmemBc+MMsHJ1P1QvPl8R8p2aPvvVcKBbvHnQOKBpBztEo0omN0eaob6FeZS/e3y9NSe+mfu3nNFBHszqkjTA== -"@nomicfoundation/ethereumjs-statemanager@2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-statemanager/-/ethereumjs-statemanager-2.0.0.tgz#d935c7dc96fd4b83106e86ac6a1cc7d3a6e7278c" - integrity sha512-tgXtsx8yIDlxWMN+ThqPtGK0ITAuITrDy+GYIgGrnT6ZtelvXWM7SUYR0Mcv578lmGCoIwyHFtSBqOkOBYHLjw== +"@nomicfoundation/ethereumjs-statemanager@2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-statemanager/-/ethereumjs-statemanager-2.0.2.tgz#3ba4253b29b1211cafe4f9265fee5a0d780976e0" + integrity sha512-dlKy5dIXLuDubx8Z74sipciZnJTRSV/uHG48RSijhgm1V7eXYFC567xgKtsKiVZB1ViTP9iFL4B6Je0xD6X2OA== dependencies: - "@nomicfoundation/ethereumjs-common" "4.0.0" - "@nomicfoundation/ethereumjs-rlp" "5.0.0" + "@nomicfoundation/ethereumjs-common" "4.0.2" + "@nomicfoundation/ethereumjs-rlp" "5.0.2" debug "^4.3.3" ethereum-cryptography "0.1.3" ethers "^5.7.1" js-sdsl "^4.1.4" -"@nomicfoundation/ethereumjs-trie@6.0.0": - version "6.0.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-trie/-/ethereumjs-trie-6.0.0.tgz#71880ee6f5bc3dec296662dafa101778915fed01" - integrity sha512-YqPWiNxrZvL+Ef7KHqgru1IlaIGXhu78wd2fxNFOvi/NAQBF845dVfTKKXs1L9x0QBRRQRephgxHCKMuISGppw== +"@nomicfoundation/ethereumjs-trie@6.0.2": + version "6.0.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-trie/-/ethereumjs-trie-6.0.2.tgz#9a6dbd28482dca1bc162d12b3733acab8cd12835" + integrity sha512-yw8vg9hBeLYk4YNg5MrSJ5H55TLOv2FSWUTROtDtTMMmDGROsAu+0tBjiNGTnKRi400M6cEzoFfa89Fc5k8NTQ== dependencies: - "@nomicfoundation/ethereumjs-rlp" "5.0.0" - "@nomicfoundation/ethereumjs-util" "9.0.0" + "@nomicfoundation/ethereumjs-rlp" "5.0.2" + "@nomicfoundation/ethereumjs-util" "9.0.2" "@types/readable-stream" "^2.3.13" ethereum-cryptography "0.1.3" readable-stream "^3.6.0" -"@nomicfoundation/ethereumjs-tx@5.0.0": - version "5.0.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-tx/-/ethereumjs-tx-5.0.0.tgz#e421063090b9a1fac4796be97aef2329af5a0ea7" - integrity sha512-LTyxI+zBJ+HuEBblUGbxvfKl1hg1uJlz2XhnszNagiBWQSgLb1vQCa1QaXV5Q8cUDYkr/Xe4NXWiUGEvH4e6lA== +"@nomicfoundation/ethereumjs-tx@5.0.2": + version "5.0.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-tx/-/ethereumjs-tx-5.0.2.tgz#117813b69c0fdc14dd0446698a64be6df71d7e56" + integrity sha512-T+l4/MmTp7VhJeNloMkM+lPU3YMUaXdcXgTGCf8+ZFvV9NYZTRLFekRwlG6/JMmVfIfbrW+dRRJ9A6H5Q/Z64g== dependencies: "@chainsafe/ssz" "^0.9.2" "@ethersproject/providers" "^5.7.2" - "@nomicfoundation/ethereumjs-common" "4.0.0" - "@nomicfoundation/ethereumjs-rlp" "5.0.0" - "@nomicfoundation/ethereumjs-util" "9.0.0" + "@nomicfoundation/ethereumjs-common" "4.0.2" + "@nomicfoundation/ethereumjs-rlp" "5.0.2" + "@nomicfoundation/ethereumjs-util" "9.0.2" ethereum-cryptography "0.1.3" -"@nomicfoundation/ethereumjs-util@9.0.0": - version "9.0.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-util/-/ethereumjs-util-9.0.0.tgz#980f6793278929f8f27f97d29cacd890459ac2b3" - integrity sha512-9EG98CsEC9BnI7AY27F4QXZ8Vf0re8R9XoxQ0//KWF+B7quu6GQvgTq1RlNUjGh/XNCCJNf8E3LOY9ULR85wFQ== +"@nomicfoundation/ethereumjs-util@9.0.2": + version "9.0.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-util/-/ethereumjs-util-9.0.2.tgz#16bdc1bb36f333b8a3559bbb4b17dac805ce904d" + integrity sha512-4Wu9D3LykbSBWZo8nJCnzVIYGvGCuyiYLIJa9XXNVt1q1jUzHdB+sJvx95VGCpPkCT+IbLecW6yfzy3E1bQrwQ== dependencies: "@chainsafe/ssz" "^0.10.0" - "@nomicfoundation/ethereumjs-rlp" "5.0.0" + "@nomicfoundation/ethereumjs-rlp" "5.0.2" ethereum-cryptography "0.1.3" -"@nomicfoundation/ethereumjs-vm@7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-vm/-/ethereumjs-vm-7.0.0.tgz#d1a511deccd1d2cf55c7d48de761749b1a86f422" - integrity sha512-eHkEoe/4r4+g+fZyIIlQjBHEjCPFs8CHiIEEMvMfvFrV4hyHnuTg4LH7l92ok7TGZqpWxgMG2JOEUFkNsXrKuQ== - dependencies: - "@nomicfoundation/ethereumjs-block" "5.0.0" - "@nomicfoundation/ethereumjs-blockchain" "7.0.0" - "@nomicfoundation/ethereumjs-common" "4.0.0" - "@nomicfoundation/ethereumjs-evm" "2.0.0" - "@nomicfoundation/ethereumjs-rlp" "5.0.0" - "@nomicfoundation/ethereumjs-statemanager" "2.0.0" - "@nomicfoundation/ethereumjs-trie" "6.0.0" - "@nomicfoundation/ethereumjs-tx" "5.0.0" - "@nomicfoundation/ethereumjs-util" "9.0.0" +"@nomicfoundation/ethereumjs-vm@7.0.2": + version "7.0.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-vm/-/ethereumjs-vm-7.0.2.tgz#3b0852cb3584df0e18c182d0672a3596c9ca95e6" + integrity sha512-Bj3KZT64j54Tcwr7Qm/0jkeZXJMfdcAtRBedou+Hx0dPOSIgqaIr0vvLwP65TpHbak2DmAq+KJbW2KNtIoFwvA== + dependencies: + "@nomicfoundation/ethereumjs-block" "5.0.2" + "@nomicfoundation/ethereumjs-blockchain" "7.0.2" + "@nomicfoundation/ethereumjs-common" "4.0.2" + "@nomicfoundation/ethereumjs-evm" "2.0.2" + "@nomicfoundation/ethereumjs-rlp" "5.0.2" + "@nomicfoundation/ethereumjs-statemanager" "2.0.2" + "@nomicfoundation/ethereumjs-trie" "6.0.2" + "@nomicfoundation/ethereumjs-tx" "5.0.2" + "@nomicfoundation/ethereumjs-util" "9.0.2" debug "^4.3.3" ethereum-cryptography "0.1.3" mcl-wasm "^0.7.1" @@ -1504,9 +1504,9 @@ url "^0.11.0" "@scure/base@~1.1.0": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.1.tgz#ebb651ee52ff84f420097055f4bf46cfba403938" - integrity sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA== + version "1.1.5" + resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.5.tgz#1d85d17269fe97694b9c592552dd9e5e33552157" + integrity sha512-Brj9FiG2W1MRQSTB212YVPRrcbjkv48FoZi/u4l/zds/ieRrqsh7aUf6CLwkAq61oKXr/ZlTzlY66gLIj3TFTQ== "@scure/bip32@1.1.5": version "1.1.5" @@ -1771,9 +1771,9 @@ "@types/node" "*" "@types/bn.js@^5.1.0": - version "5.1.1" - resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.1.tgz#b51e1b55920a4ca26e9285ff79936bbdec910682" - integrity sha512-qNrYbZqMx0uJAfKnKclPh+dTwK33KfLHYqtyODwd5HnXOjnkhc4qgn3BrK6RWyGZm5+sIFE7Q7Vz6QQtJB7w7g== + version "5.1.5" + resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.5.tgz#2e0dacdcce2c0f16b905d20ff87aedbc6f7b4bf0" + integrity sha512-V46N0zwKRF5Q00AZ6hWtN0T8gGmDUaUzLWQvHFo5yThtVwK/VCenFY3wXVbOvNfajEpsTfQM4IN9k/d6gUVX3A== dependencies: "@types/node" "*" @@ -1894,10 +1894,12 @@ "@types/node" "*" form-data "^3.0.0" -"@types/node@*", "@types/node@^18.15.11": - version "18.15.11" - resolved "https://registry.yarnpkg.com/@types/node/-/node-18.15.11.tgz#b3b790f09cb1696cffcec605de025b088fa4225f" - integrity sha512-E5Kwq2n4SbMzQOn6wnmBjuK9ouqlURrcZDVfbo9ftDDTFt3nk7ZKK4GMOzoYgnpQJKcxwQw+lGaBvvlMo0qN/Q== +"@types/node@*": + version "20.10.5" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.10.5.tgz#47ad460b514096b7ed63a1dae26fad0914ed3ab2" + integrity sha512-nNPsNE65wjMxEKI93yOP+NPGGBJz/PoN3kZsVLee0XMiJolxSekEVD8wRwBUBqkwc7UWop0edW50yrCQW4CyRw== + dependencies: + undici-types "~5.26.4" "@types/node@11.11.6": version "11.11.6" @@ -1914,6 +1916,11 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.55.tgz#c329cbd434c42164f846b909bd6f85b5537f6240" integrity sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ== +"@types/node@^18.15.11": + version "18.15.11" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.15.11.tgz#b3b790f09cb1696cffcec605de025b088fa4225f" + integrity sha512-E5Kwq2n4SbMzQOn6wnmBjuK9ouqlURrcZDVfbo9ftDDTFt3nk7ZKK4GMOzoYgnpQJKcxwQw+lGaBvvlMo0qN/Q== + "@types/node@^8.0.0": version "8.10.66" resolved "https://registry.yarnpkg.com/@types/node/-/node-8.10.66.tgz#dd035d409df322acc83dff62a602f12a5783bbb3" @@ -1925,9 +1932,9 @@ integrity sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw== "@types/pbkdf2@^3.0.0": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@types/pbkdf2/-/pbkdf2-3.1.0.tgz#039a0e9b67da0cdc4ee5dab865caa6b267bb66b1" - integrity sha512-Cf63Rv7jCQ0LaL8tNXmEyqTHuIJxRdlS5vMh1mj5voN4+QFhVZnlZruezqpWYDiJ8UTzhP0VmeLXCmBk66YrMQ== + version "3.1.2" + resolved "https://registry.yarnpkg.com/@types/pbkdf2/-/pbkdf2-3.1.2.tgz#2dc43808e9985a2c69ff02e2d2027bd4fe33e8dc" + integrity sha512-uRwJqmiXmh9++aSu1VNEn3iIxWOhd8AHXNSdlaLfdAAdSTY9jYVeGWnzejM3dvrkbqE3/hyQkQQ29IFATEGlew== dependencies: "@types/node" "*" @@ -1950,9 +1957,9 @@ safe-buffer "~5.1.1" "@types/secp256k1@^4.0.1": - version "4.0.3" - resolved "https://registry.yarnpkg.com/@types/secp256k1/-/secp256k1-4.0.3.tgz#1b8e55d8e00f08ee7220b4d59a6abe89c37a901c" - integrity sha512-Da66lEIFeIz9ltsdMZcpQvmrmmoqrfju8pm1BH8WbYjZSwUgCwXLb9C+9XYogwBITnbsSaMdVPb2ekf7TV+03w== + version "4.0.6" + resolved "https://registry.yarnpkg.com/@types/secp256k1/-/secp256k1-4.0.6.tgz#d60ba2349a51c2cbc5e816dcd831a42029d376bf" + integrity sha512-hHxJU6PAEUn0TP4S/ZOzuTUvJWuZ6eIKeNKb5RBpODvSl6hp1Wrw4s7ATY50rklRCScUDpHzVA/DQdSjJ3UoYQ== dependencies: "@types/node" "*" @@ -2135,13 +2142,6 @@ abbrev@1.0.x: resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.0.9.tgz#91b4792588a7738c25f35dd6f63752a2f8776135" integrity sha512-LEyx4aLEC3x6T0UguF6YILf+ntvmOaWsVfENmIW0E9H09vKlLDGelMjjSm0jkDHALj8A8quZ/HapKNigzwge+Q== -abort-controller@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" - integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== - dependencies: - event-target-shim "^5.0.0" - abstract-level@^1.0.0, abstract-level@^1.0.2, abstract-level@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/abstract-level/-/abstract-level-1.0.3.tgz#78a67d3d84da55ee15201486ab44c09560070741" @@ -2806,9 +2806,9 @@ before-after-hook@^2.2.0: integrity sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ== bigint-crypto-utils@^3.0.23: - version "3.2.2" - resolved "https://registry.yarnpkg.com/bigint-crypto-utils/-/bigint-crypto-utils-3.2.2.tgz#e30a49ec38357c6981cd3da5aaa6480b1f752ee4" - integrity sha512-U1RbE3aX9ayCUVcIPHuPDPKcK3SFOXf93J1UK/iHlJuQB7bhagPIX06/CLpLEsDThJ7KA4Dhrnzynl+d2weTiw== + version "3.3.0" + resolved "https://registry.yarnpkg.com/bigint-crypto-utils/-/bigint-crypto-utils-3.3.0.tgz#72ad00ae91062cf07f2b1def9594006c279c1d77" + integrity sha512-jOTSb+drvEDxEq6OuUybOAv/xxoh3cuYRUIPyu8sSHQNKM303UQ2R1DAo45o1AkcIXw6fzbaFI1+xGGdaXs2lg== bignumber.js@^9.0.0, bignumber.js@^9.0.1: version "9.1.1" @@ -3087,7 +3087,16 @@ cacache@^17.0.0: tar "^6.1.11" unique-filename "^3.0.0" -call-bind@^1.0.0, call-bind@^1.0.2: +call-bind@^1.0.0: + version "1.0.5" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.5.tgz#6fa2b7845ce0ea49bf4d8b9ef64727a2c2e2e513" + integrity sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ== + dependencies: + function-bind "^1.1.2" + get-intrinsic "^1.2.1" + set-function-length "^1.1.1" + +call-bind@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== @@ -3797,6 +3806,15 @@ deferred-leveldown@~5.3.0: abstract-leveldown "~6.2.1" inherits "^2.0.3" +define-data-property@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.1.tgz#c35f7cd0ab09883480d12ac5cb213715587800b3" + integrity sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ== + dependencies: + get-intrinsic "^1.2.1" + gopd "^1.0.1" + has-property-descriptors "^1.0.0" + define-lazy-prop@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f" @@ -4040,7 +4058,15 @@ end-of-stream@^1.4.1: dependencies: once "^1.4.0" -enquirer@^2.3.0, enquirer@~2.3.6: +enquirer@^2.3.0: + version "2.4.1" + resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.4.1.tgz#93334b3fbd74fc7097b224ab4a8fb7e40bf4ae56" + integrity sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ== + dependencies: + ansi-colors "^4.1.1" + strip-ansi "^6.0.1" + +enquirer@~2.3.6: version "2.3.6" resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg== @@ -4532,11 +4558,6 @@ ethjs-util@0.1.6, ethjs-util@^0.1.6: is-hex-prefixed "1.0.0" strip-hex-prefix "1.0.0" -event-target-shim@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" - integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== - eventemitter3@^4.0.4: version "4.0.7" resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" @@ -4827,9 +4848,9 @@ flatted@^3.1.0: integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ== follow-redirects@^1.12.1, follow-redirects@^1.15.0: - version "1.15.2" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" - integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== + version "1.15.4" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.4.tgz#cdc7d308bf6493126b17ea2191ea0ccf3e535adf" + integrity sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw== for-each@^0.3.3: version "0.3.3" @@ -5007,14 +5028,14 @@ fsevents@~2.1.1: integrity sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ== fsevents@~2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" - integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + version "2.3.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== -function-bind@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" - integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== +function-bind@^1.1.1, function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== function.prototype.name@^1.1.5: version "1.1.5" @@ -5082,7 +5103,17 @@ get-func-name@^2.0.0: resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.2.tgz#0d7cf20cd13fda808669ffa88f4ffc7a3943fc41" integrity sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ== -get-intrinsic@^1.0.2, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3, get-intrinsic@^1.2.0: +get-intrinsic@^1.0.2, get-intrinsic@^1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.2.tgz#281b7622971123e1ef4b3c90fd7539306da93f3b" + integrity sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA== + dependencies: + function-bind "^1.1.2" + has-proto "^1.0.1" + has-symbols "^1.0.3" + hasown "^2.0.0" + +get-intrinsic@^1.1.1, get-intrinsic@^1.1.3, get-intrinsic@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.0.tgz#7ad1dc0535f3a2904bba075772763e5051f6d05f" integrity sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q== @@ -5431,27 +5462,26 @@ hardhat-gas-reporter@^1.0.9: sha1 "^1.1.1" hardhat@^2.12.7: - version "2.13.1" - resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.13.1.tgz#12380aef6aa8ce67517e8ee166998be5ced8970e" - integrity sha512-ZZL7LQxHmbw4JQJsiEv2qE35nbR+isr2sIdtgZVPp0+zWqRkpr1OT7gmvhCNYfjpEPyfjZIxWriQWlphJhVPLQ== + version "2.19.4" + resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.19.4.tgz#5112c30295d8be2e18e55d847373c50483ed1902" + integrity sha512-fTQJpqSt3Xo9Mn/WrdblNGAfcANM6XC3tAEi6YogB4s02DmTf93A8QsGb8uR0KR8TFcpcS8lgiW4ugAIYpnbrQ== dependencies: "@ethersproject/abi" "^5.1.2" "@metamask/eth-sig-util" "^4.0.0" - "@nomicfoundation/ethereumjs-block" "5.0.0" - "@nomicfoundation/ethereumjs-blockchain" "7.0.0" - "@nomicfoundation/ethereumjs-common" "4.0.0" - "@nomicfoundation/ethereumjs-evm" "2.0.0" - "@nomicfoundation/ethereumjs-rlp" "5.0.0" - "@nomicfoundation/ethereumjs-statemanager" "2.0.0" - "@nomicfoundation/ethereumjs-trie" "6.0.0" - "@nomicfoundation/ethereumjs-tx" "5.0.0" - "@nomicfoundation/ethereumjs-util" "9.0.0" - "@nomicfoundation/ethereumjs-vm" "7.0.0" + "@nomicfoundation/ethereumjs-block" "5.0.2" + "@nomicfoundation/ethereumjs-blockchain" "7.0.2" + "@nomicfoundation/ethereumjs-common" "4.0.2" + "@nomicfoundation/ethereumjs-evm" "2.0.2" + "@nomicfoundation/ethereumjs-rlp" "5.0.2" + "@nomicfoundation/ethereumjs-statemanager" "2.0.2" + "@nomicfoundation/ethereumjs-trie" "6.0.2" + "@nomicfoundation/ethereumjs-tx" "5.0.2" + "@nomicfoundation/ethereumjs-util" "9.0.2" + "@nomicfoundation/ethereumjs-vm" "7.0.2" "@nomicfoundation/solidity-analyzer" "^0.1.0" "@sentry/node" "^5.18.1" "@types/bn.js" "^5.1.0" "@types/lru-cache" "^5.1.0" - abort-controller "^3.0.0" adm-zip "^0.4.16" aggregate-error "^3.0.0" ansi-escapes "^4.3.0" @@ -5474,7 +5504,6 @@ hardhat@^2.12.7: mnemonist "^0.38.0" mocha "^10.0.0" p-map "^4.0.0" - qs "^6.7.0" raw-body "^2.4.1" resolve "1.17.0" semver "^6.3.0" @@ -5536,11 +5565,9 @@ has-unicode@2.0.1, has-unicode@^2.0.1: integrity sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ== has@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" - integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== - dependencies: - function-bind "^1.1.1" + version "1.0.4" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.4.tgz#2eb2860e000011dae4f1406a86fe80e530fb2ec6" + integrity sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ== hash-base@^3.0.0: version "3.1.0" @@ -5567,6 +5594,13 @@ hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3, hash.js@^1.1.7: inherits "^2.0.3" minimalistic-assert "^1.0.1" +hasown@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.0.tgz#f4c513d454a57b7c7e1650778de226b11700546c" + integrity sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA== + dependencies: + function-bind "^1.1.2" + he@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" @@ -5737,9 +5771,9 @@ immediate@~3.2.3: integrity sha512-RrGCXRm/fRVqMIhqXrGEX9rRADavPiDFSoMb/k64i9XMk8uH4r/Omi5Ctierj6XzNecwDbO4WuFbDD1zmpl3Tg== immutable@^4.0.0-rc.12: - version "4.3.0" - resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.3.0.tgz#eb1738f14ffb39fd068b1dbe1296117484dd34be" - integrity sha512-0AOCmOip+xgJwEVTQj1EfiDDOkPmuyllDuTuEX+DDXUgapLAsBIfkg3sxCYyCEA8mQqZrrxPUGjcOQ2JS3WLkg== + version "4.3.4" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.3.4.tgz#2e07b33837b4bb7662f288c244d1ced1ef65a78f" + integrity sha512-fsXeu4J4i6WNWSikpI88v/PcVflZz+6kMhUfIwc5SY+poQRPnaf5V7qds6SUyUN3cVxEzuCab7QIoLOQ+DQ1wA== import-fresh@^3.0.0, import-fresh@^3.2.1, import-fresh@^3.3.0: version "3.3.0" @@ -6267,9 +6301,9 @@ jest-get-type@^29.6.3: integrity sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw== js-sdsl@^4.1.4: - version "4.4.0" - resolved "https://registry.yarnpkg.com/js-sdsl/-/js-sdsl-4.4.0.tgz#8b437dbe642daa95760400b602378ed8ffea8430" - integrity sha512-FfVSdx6pJ41Oa+CF7RDaFmTnCaFhua+SNYQX74riGOpl96x+2jQCqEfQ2bnXu/5DPCqlRuiqyvTJM0Qjz26IVg== + version "4.4.2" + resolved "https://registry.yarnpkg.com/js-sdsl/-/js-sdsl-4.4.2.tgz#2e3c031b1f47d3aca8b775532e3ebb0818e7f847" + integrity sha512-dwXFwByc/ajSV6m5bcKAPwe4yDDF6D614pxmIi5odytzxRlwqF6nwoiCek80Ixc7Cvma5awClxrzFtxCQvcM8w== js-sha3@0.5.7: version "0.5.7" @@ -6437,9 +6471,9 @@ keccak@3.0.2: readable-stream "^3.6.0" keccak@^3.0.0, keccak@^3.0.2: - version "3.0.3" - resolved "https://registry.yarnpkg.com/keccak/-/keccak-3.0.3.tgz#4bc35ad917be1ef54ff246f904c2bbbf9ac61276" - integrity sha512-JZrLIAJWuZxKbCilMpNz5Vj7Vtb4scDG3dMXLOsbzBmQGyjwE61BbW7bJkfKKCShXiQZt3T6sBgALRtmd+nZaQ== + version "3.0.4" + resolved "https://registry.yarnpkg.com/keccak/-/keccak-3.0.4.tgz#edc09b89e633c0549da444432ecf062ffadee86d" + integrity sha512-3vKuW0jV8J3XNTzvfyicFR5qvxrSAGl7KIhvgOu5cmWwM7tZRj3fMbj/pfIf4be7aznbc+prBWGjywox/g2Y6Q== dependencies: node-addon-api "^2.0.0" node-gyp-build "^4.2.0" @@ -7659,9 +7693,9 @@ node-gyp-build@4.4.0: integrity sha512-amJnQCcgtRVw9SvoebO3BKGESClrfXGCUTX9hSn1OuGQTQBOZmVd0Z0OlecpuRksKvbsUqALE8jls/ErClAPuQ== node-gyp-build@^4.2.0, node-gyp-build@^4.3.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.6.0.tgz#0c52e4cbf54bbd28b709820ef7b6a3c2d6209055" - integrity sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ== + version "4.7.1" + resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.7.1.tgz#cd7d2eb48e594874053150a9418ac85af83ca8f7" + integrity sha512-wTSrZ+8lsRRa3I3H8Xr65dLWSgCvY2l4AOnaeKdPA9TB/WYMPaTcrzf3rXvFoVvjKNVnu0CcWSx54qq9GKRUYg== node-gyp@^9.0.0: version "9.3.1" @@ -7996,11 +8030,16 @@ object-copy@^0.1.0: define-property "^0.2.5" kind-of "^3.0.3" -object-inspect@^1.12.3, object-inspect@^1.9.0: +object-inspect@^1.12.3: version "1.12.3" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9" integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g== +object-inspect@^1.9.0: + version "1.13.1" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.1.tgz#b96c6109324ccfef6b12216a956ca4dc2ff94bc2" + integrity sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ== + object-keys@^1.0.11, object-keys@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" @@ -8630,13 +8669,6 @@ qs@^6.4.0: dependencies: side-channel "^1.0.4" -qs@^6.7.0: - version "6.11.1" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.1.tgz#6c29dff97f0c0060765911ba65cbc9764186109f" - integrity sha512-0wsrzgTz/kAVIeuxSjnpGC56rzYtr6JT/2BwEvMaPhFIoYa1aGO8LbzuU1R0uUYQkLpWBTOj0l/CLAJB64J6nQ== - dependencies: - side-channel "^1.0.4" - qs@~6.5.2: version "6.5.3" resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.3.tgz#3aeeffc91967ef6e35c0e488ef46fb296ab76aad" @@ -9173,9 +9205,9 @@ semver@7.5.3: lru-cache "^6.0.0" semver@^6.3.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" - integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== + version "6.3.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== semver@^7.0.0, semver@^7.1.1, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.3: version "7.5.4" @@ -9225,6 +9257,16 @@ set-blocking@^2.0.0: resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== +set-function-length@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.1.1.tgz#4bc39fafb0307224a33e106a7d35ca1218d659ed" + integrity sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ== + dependencies: + define-data-property "^1.1.1" + get-intrinsic "^1.2.1" + gopd "^1.0.1" + has-property-descriptors "^1.0.0" + set-getter@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/set-getter/-/set-getter-0.1.1.tgz#a3110e1b461d31a9cfc8c5c9ee2e9737ad447102" @@ -10246,10 +10288,15 @@ unbox-primitive@^1.0.2: has-symbols "^1.0.3" which-boxed-primitive "^1.0.2" +undici-types@~5.26.4: + version "5.26.5" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" + integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== + undici@^5.14.0: - version "5.26.3" - resolved "https://registry.yarnpkg.com/undici/-/undici-5.26.3.tgz#ab3527b3d5bb25b12f898dfd22165d472dd71b79" - integrity sha512-H7n2zmKEWgOllKkIUkLvFmsJQj062lSm3uA4EYApG8gLuiOM0/go9bIoC3HVaSnfg4xunowDE2i9p8drkXuvDw== + version "5.28.2" + resolved "https://registry.yarnpkg.com/undici/-/undici-5.28.2.tgz#fea200eac65fc7ecaff80a023d1a0543423b4c91" + integrity sha512-wh1pHJHnUeQV5Xa8/kyQhO7WFa8M34l026L5P/+2TYiakvGy5Rdc8jWZVyG7ieht/0WgJLEd3kcU5gKx+6GC8w== dependencies: "@fastify/busboy" "^2.0.0"