From 6648eb5e0cf38d0adc4b0c95108d24c42e1b0b90 Mon Sep 17 00:00:00 2001 From: Joao Victor Pereira Santos Date: Tue, 19 Dec 2023 12:31:52 -0300 Subject: [PATCH 1/7] feat: [ISSUE-119] Adding receiver parameter to swap function and create approveToken script --- contracts/Swaplace.sol | 4 +- contracts/echidna/TestSwaplace.sol | 2 +- contracts/interfaces/ISwaplace.sol | 2 +- estimateGasOfEvents.md | 117 +++++++++++++++++++++++++++++ scripts/acceptSwap.ts | 4 +- scripts/approveToken.ts | 33 ++++++++ scripts/deploySepolia.ts | 25 ++++++ scripts/estimateGasOfEvents.ts | 59 +++++++++++++++ test/utils/utils.ts | 16 ++++ 9 files changed, 256 insertions(+), 6 deletions(-) create mode 100644 estimateGasOfEvents.md create mode 100644 scripts/approveToken.ts create mode 100644 scripts/deploySepolia.ts create mode 100644 scripts/estimateGasOfEvents.ts diff --git a/contracts/Swaplace.sol b/contracts/Swaplace.sol index 5a672ee..2a2564d 100644 --- a/contracts/Swaplace.sol +++ b/contracts/Swaplace.sol @@ -54,7 +54,7 @@ contract Swaplace is SwapFactory, ISwaplace, IERC165 { /** * @dev See {ISwaplace-acceptSwap}. */ - function acceptSwap(uint256 swapId) public returns (bool) { + function acceptSwap(uint256 swapId, address receiver) public returns (bool) { Swap memory swap = _swaps[swapId]; if (swap.allowed != address(0) && swap.allowed != msg.sender) { @@ -85,7 +85,7 @@ contract Swaplace is SwapFactory, ISwaplace, IERC165 { for (uint256 i = 0; i < assets.length; ) { ITransfer(assets[i].addr).transferFrom( swap.owner, - msg.sender, + receiver, assets[i].amountOrId ); unchecked { diff --git a/contracts/echidna/TestSwaplace.sol b/contracts/echidna/TestSwaplace.sol index 8e76b3e..38d398f 100644 --- a/contracts/echidna/TestSwaplace.sol +++ b/contracts/echidna/TestSwaplace.sol @@ -32,7 +32,7 @@ contract TestSwaplace is TestFactory { _token.approve(address(_swaplace), type(uint256).max); uint256 lastId = _swaplace.totalSwaps(); - return (_swaplace.acceptSwap(lastId)); + return (_swaplace.acceptSwap(lastId, address(0))); } function echidna_id_overflow() public view returns (bool) { diff --git a/contracts/interfaces/ISwaplace.sol b/contracts/interfaces/ISwaplace.sol index 0ff9378..a4e8fd2 100644 --- a/contracts/interfaces/ISwaplace.sol +++ b/contracts/interfaces/ISwaplace.sol @@ -55,7 +55,7 @@ interface ISwaplace { * NOTE: The expiry is set to 0, because if the Swap is expired it * will revert, preventing reentrancy attacks. */ - function acceptSwap(uint256 swapId) external returns (bool); + function acceptSwap(uint256 swapId, address receiver) external returns (bool); /** * @dev Cancels an active Swap by setting the expiry to zero. diff --git a/estimateGasOfEvents.md b/estimateGasOfEvents.md new file mode 100644 index 0000000..371091e --- /dev/null +++ b/estimateGasOfEvents.md @@ -0,0 +1,117 @@ +# docs: research gas and cost efficiency for event emission + +## How I calculated the gas usage? + +- Example: + +``` +uint256 startGas = gasleft(); + +// code + +gasUsed = startGas - gasleft(); +``` + +## Prepare a spreadsheet with the gas usage based on the current and proposed events emitted and set for a comparison. + +- In the document I separeted a comparison about the options to emit events :) + +## Estimate the gas when calling createSwap and record their gas usage. + +- When we call the "createSwap" event with the current parameters (id, owner and expiry) the gas usage is 1932. + +``` +event SwapCreated( + uint256 indexed id, + address indexed owner, + uint256 indexed expiry +); +``` + +``` +emit SwapCreated(swapId, msg.sender, swap.expiry); +``` + +- But we can optimize with assembly, so the gas usage can be: 1919 + +``` +//keccak-256(SwapCreated(uint256,address,uint256)) +bytes32 private constant EVENT_SWAP_CREATED_SIGNATURE = + 0xecac413765eac3982e66e569ad3a200e6b3f188ac4d7d44cc5da667779ca8d05; +``` + +``` +uint256 swapExpiry = swap.expiry; +assembly { + log4(0x00, 0x00, EVENT_SWAP_CREATED_SIGNATURE, swapId, caller(), swapExpiry) +} +``` + +## Take measures of the gas usage. + +- I change the emit of events to use assembly to reduce the gas usage. + +## Add the allowed field in the events. Take Measure. + +- Gas usage with Solidity: 2702 + +``` +event SwapCreated( + uint256 indexed id, + address indexed owner, + uint256 indexed expiry, + address allowed +); +``` + +``` +emit SwapCreated(swapId, msg.sender, swap.expiry, swap.allowed); +``` + +- But we can optimize with assembly, so the gas usage can be: 2502 + +``` +//keccak-256(SwapCreated(uint256,address,uint256,address)) +bytes32 private constant EVENT_SWAP_CREATED_SIGNATURE = + 0x43a58bfac3282e5ce3bfd714c5bc0ddff8d6f2cd049db0b02a25d7cdd5026efb; +``` + +``` +uint256 swapExpiry = swap.expiry; +address allowed = swap.allowed; +assembly { + mstore(0x00, allowed) + log4(0x00, 0x20, EVENT_SWAP_CREATED_SIGNATURE, swapId, caller(), swapExpiry) +} +``` + +## Add the bidding and asking field in the events. Take Measure. + +- Gas usage with Solidity: 7646 + +``` +event SwapCreated( + uint256 indexed id, + address indexed owner, + uint256 indexed expiry, + address allowed, + ISwap.Asset[] biding, + ISwap.Asset[] asking +); +``` + +``` +emit SwapCreated(swapId, msg.sender, swap.expiry, swap.allowed, swap.biding, swap.asking); +``` + +## Add the price of ETH at $2.200 and calculate the gas cost in dollars. + +- I don't know how I can make this setting the ETH value. (help me please :) + +# Conclusion + +- After the study about gas usage in the swaplace, I came to the conclusion that we can add the "allowed" field in the "SwapCreated" event, but if we add the "biding" and "asking" fields, we will increase a lot the gas usage in the emit of events, so I this PR I added the "allowed" field in the swap created event and refactored all events to use assembly to reduce the gas usage. + +- And about the "biding" and "asking" fields, I think that is have a lot of gas usage and I'm studying about how we can emit the event with assembly there paramters, I tried but I couldn't, I'm trying yet :) + +- If possible, I need your review about this PR :), I'm ready to fix/improve something and work togheter!!! \ No newline at end of file diff --git a/scripts/acceptSwap.ts b/scripts/acceptSwap.ts index 8ea1032..798c382 100644 --- a/scripts/acceptSwap.ts +++ b/scripts/acceptSwap.ts @@ -3,7 +3,7 @@ import abi from "../artifacts/contracts/Swaplace.sol/Swaplace.json"; export async function main() { // Get the first account from the list of accounts - const [signer] = await ethers.getSigners(); + const [signer, receiver] = await ethers.getSigners(); // Get the Swaplace address from .env file const swaplaceAddress: string = process.env.SWAPLACE_ADDRESS || ""; @@ -15,7 +15,7 @@ export async function main() { const swapId = 1; // Accept the swap - const tx = await Swaplace.acceptSwap(swapId); + const tx = await Swaplace.acceptSwap(swapId, receiver.address); // Wait for the transaction to be mined await tx.wait(); diff --git a/scripts/approveToken.ts b/scripts/approveToken.ts new file mode 100644 index 0000000..63aa195 --- /dev/null +++ b/scripts/approveToken.ts @@ -0,0 +1,33 @@ +import { ethers } from "hardhat" +import { ERC20ABI } from "../test/utils/utils"; + +export async function main() { + // Get the first account from the list of accounts + const [signer] = await ethers.getSigners(); + + // Get the Swaplace address from .env file + const swaplaceAddress: string = process.env.SWAPLACE_ADDRESS || ""; + + // Get the token contract, replace to the token that you want approve + const tokenContract = ''; + + // Get the token instance + const Token = new ethers.Contract(tokenContract, ERC20ABI, signer); + + // Get the value to approve token, replace to value that you need + const valueApproveToken = BigInt(99999 * (10**18)); + + // Make the approve + const tx = Token.approve(swaplaceAddress, valueApproveToken) + + // Wait for the transaction to be mined + await tx.wait(); + + // Log the transaction hash + console.log("\nTransaction Hash: ", tx); +} + +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); diff --git a/scripts/deploySepolia.ts b/scripts/deploySepolia.ts new file mode 100644 index 0000000..c9d93af --- /dev/null +++ b/scripts/deploySepolia.ts @@ -0,0 +1,25 @@ +import { ethers } from "ethers"; +import { deploy } from "../test/utils/utils" + +async function main() { + const provider = new ethers.providers.JsonRpcProvider( + "https://eth-sepolia.g.alchemy.com/v2/0hrAreDXB2XfRlTyKef9Wf_ZHhkojj6I" + ) + const wallet = new ethers.Wallet("1110eba3679d276d85f5aa0db74aef5456d7bf7e3185ab5ab623ecfe74014893", provider) + + // Deploy in the currrent network and return the Swaplace instance + const Swaplace = await deploy("Swaplace", wallet) + + // Log Contract address, the Tx then return the Contract instance + console.log( + "\nContract %s \nDeployed to %s \nAt Tx %s", + "Swaplace", + Swaplace.address, + Swaplace.deployTransaction.hash + ) +} + +main().catch((error) => { + console.error(error) + process.exitCode = 1 +}) diff --git a/scripts/estimateGasOfEvents.ts b/scripts/estimateGasOfEvents.ts new file mode 100644 index 0000000..e67cb2c --- /dev/null +++ b/scripts/estimateGasOfEvents.ts @@ -0,0 +1,59 @@ +import { ethers } from "hardhat"; +import { blocktimestamp } from "../test/utils/utils"; +import { Swap, composeSwap } from "../test/utils/SwapFactory"; +import abi from "../artifacts/contracts/Swaplace.sol/Swaplace.json"; +import { deploy } from "../test/utils/utils"; + +export async function main() { + // Get the first account from the list of accounts + const [signer] = await ethers.getSigners(); + + // Get the Swaplace address from .env file + // const swaplaceAddress: string = process.env.SWAPLACE_ADDRESS || ""; + + // Get the Swaplace instance + // const Swaplace = new ethers.Contract(swaplaceAddress, abi.abi, signer); + + // Deploy in the currrent network and return the Swaplace instance + const Swaplace = await deploy("Swaplace", signer); + + // Fill the Swap struct + const owner = signer.address; + const allowed = ethers.constants.AddressZero; + const expiry = (await blocktimestamp()* 2); + + // Build the biding assets + const bidingAddr = ["0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"]; // USDC + const bidingAmountOrId = [1000]; + + // Build the asking assets + const askingAddr = ["0x2260fac5e5542a773aa44fbcfedf7c193bc2c599"]; // WBTC + const askingAmountOrId = [1]; + + // Compose the swap + const swap: Swap = await composeSwap( + owner, + allowed, + expiry, + bidingAddr, + bidingAmountOrId, + askingAddr, + askingAmountOrId + ); + + // Create the swap + let tx = await Swaplace.createSwap(swap); + + // Wait for the transaction to be mined + // await tx.wait(); + tx = await Swaplace.getGasCost(); + + // Log the transaction hash + console.log("\nGas used 'emit SwapCreated()': ", tx); +} + +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); + diff --git a/test/utils/utils.ts b/test/utils/utils.ts index 88e3b5f..4f6b30c 100644 --- a/test/utils/utils.ts +++ b/test/utils/utils.ts @@ -30,7 +30,23 @@ export async function deploy(contractName: any, signer: any) { return Contract; } +/** + * @dev ABI of ERC20 standard + */ +export const ERC20ABI = [ + "function name() public view returns (string)", + "function symbol() public view returns (string)", + "function decimals() public view returns (uint8)", + "function totalSupply() public view returns (uint256)", + "function balanceOf(address _owner) public view returns (uint256 balance)", + "function transfer(address _to, uint256 _value) public returns (bool success)", + "function transferFrom(address _from, address _to, uint256 _value) public returns (bool success)", + "function approve(address _spender, uint256 _value) public returns (bool success)", + "function allowance(address _owner, address _spender) public view returns (uint256 remaining)", +]; + module.exports = { blocktimestamp, deploy, + ERC20ABI, }; From 1325f8685971e3323613b1833b8faf765620cfeb Mon Sep 17 00:00:00 2001 From: Joao Victor Pereira Santos Date: Tue, 19 Dec 2023 12:50:12 -0300 Subject: [PATCH 2/7] test: [ISSUE-119] Change acceptSwap to support receiver parameter --- test/TestSwaplace.test.ts | 39 +++++++++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/test/TestSwaplace.test.ts b/test/TestSwaplace.test.ts index dc4cb94..2c8e965 100644 --- a/test/TestSwaplace.test.ts +++ b/test/TestSwaplace.test.ts @@ -15,6 +15,7 @@ describe("Swaplace", async function () { let deployer: SignerWithAddress; let owner: SignerWithAddress; let acceptee: SignerWithAddress; + let receiver: SignerWithAddress; // Solidity address(0) const zeroAddress = ethers.constants.AddressZero; @@ -45,7 +46,7 @@ describe("Swaplace", async function () { } before(async () => { - [deployer, owner, acceptee] = await ethers.getSigners(); + [deployer, owner, acceptee, receiver] = await ethers.getSigners(); Swaplace = await deploy("Swaplace", deployer); MockERC20 = await deploy("MockERC20", deployer); MockERC721 = await deploy("MockERC721", deployer); @@ -275,10 +276,11 @@ describe("Swaplace", async function () { await expect( await Swaplace.connect(acceptee).acceptSwap( await Swaplace.totalSwaps(), + receiver.address, ), ) .to.emit(Swaplace, "SwapAccepted") - .withArgs(await Swaplace.totalSwaps(), acceptee.address); + .withArgs(await Swaplace.totalSwaps(), receiver.address); }); it("Should be able to {acceptSwap} as N-N Swap", async function () { @@ -307,10 +309,11 @@ describe("Swaplace", async function () { await expect( await Swaplace.connect(acceptee).acceptSwap( await Swaplace.totalSwaps(), + receiver.address, ), ) .to.emit(Swaplace, "SwapAccepted") - .withArgs(await Swaplace.totalSwaps(), acceptee.address); + .withArgs(await Swaplace.totalSwaps(), receiver.address); }); it("Should be able to {acceptSwap} as P2P Swap", async function () { @@ -330,10 +333,11 @@ describe("Swaplace", async function () { await expect( await Swaplace.connect(acceptee).acceptSwap( await Swaplace.totalSwaps(), + receiver.address, ), ) .to.emit(Swaplace, "SwapAccepted") - .withArgs(await Swaplace.totalSwaps(), acceptee.address); + .withArgs(await Swaplace.totalSwaps(), receiver.address); }); }); @@ -344,13 +348,17 @@ describe("Swaplace", async function () { await expect( await Swaplace.connect(acceptee).acceptSwap( await Swaplace.totalSwaps(), + receiver.address, ), ) .to.emit(Swaplace, "SwapAccepted") - .withArgs(await Swaplace.totalSwaps(), acceptee.address); + .withArgs(await Swaplace.totalSwaps(), receiver.address); await expect( - Swaplace.connect(acceptee).acceptSwap(await Swaplace.totalSwaps()), + Swaplace.connect(acceptee).acceptSwap( + await Swaplace.totalSwaps(), + receiver.address, + ), ) .to.be.revertedWithCustomError(Swaplace, `InvalidExpiry`) .withArgs(0); @@ -362,7 +370,10 @@ describe("Swaplace", async function () { await network.provider.send("evm_increaseTime", [swap.expiry * 2]); await expect( - Swaplace.connect(owner).acceptSwap(await Swaplace.totalSwaps()), + Swaplace.connect(owner).acceptSwap( + await Swaplace.totalSwaps(), + receiver.address, + ), ) .to.be.revertedWithCustomError(Swaplace, `InvalidExpiry`) .withArgs(swap.expiry); @@ -374,7 +385,10 @@ describe("Swaplace", async function () { await Swaplace.connect(owner).createSwap(swap); await expect( - Swaplace.connect(acceptee).acceptSwap(await Swaplace.totalSwaps()), + Swaplace.connect(acceptee).acceptSwap( + await Swaplace.totalSwaps(), + receiver.address, + ), ).to.be.revertedWith(`ERC721: caller is not token owner or approved`); }); @@ -393,7 +407,10 @@ describe("Swaplace", async function () { .withArgs(await Swaplace.totalSwaps(), owner.address, swap.expiry); await expect( - Swaplace.connect(acceptee).acceptSwap(await Swaplace.totalSwaps()), + Swaplace.connect(acceptee).acceptSwap( + await Swaplace.totalSwaps(), + receiver.address, + ), ) .to.be.revertedWithCustomError(Swaplace, "InvalidAddress") .withArgs(acceptee.address); @@ -418,7 +435,9 @@ describe("Swaplace", async function () { it("Should not be able to {acceptSwap} a canceled a Swap", async function () { const lastSwap = await Swaplace.totalSwaps(); - await expect(Swaplace.connect(owner).acceptSwap(lastSwap)) + await expect( + Swaplace.connect(owner).acceptSwap(lastSwap, receiver.address), + ) .to.be.revertedWithCustomError(Swaplace, `InvalidExpiry`) .withArgs(0); }); From 6568d79397c9462201eac39e9115137d56d51bf6 Mon Sep 17 00:00:00 2001 From: Joao Victor Pereira Santos Date: Tue, 19 Dec 2023 16:34:14 -0300 Subject: [PATCH 3/7] fix: [ISSUE-119] Remove unecessary files --- scripts/deploySepolia.ts | 25 -------------- scripts/estimateGasOfEvents.ts | 59 ---------------------------------- 2 files changed, 84 deletions(-) delete mode 100644 scripts/deploySepolia.ts delete mode 100644 scripts/estimateGasOfEvents.ts diff --git a/scripts/deploySepolia.ts b/scripts/deploySepolia.ts deleted file mode 100644 index c9d93af..0000000 --- a/scripts/deploySepolia.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { ethers } from "ethers"; -import { deploy } from "../test/utils/utils" - -async function main() { - const provider = new ethers.providers.JsonRpcProvider( - "https://eth-sepolia.g.alchemy.com/v2/0hrAreDXB2XfRlTyKef9Wf_ZHhkojj6I" - ) - const wallet = new ethers.Wallet("1110eba3679d276d85f5aa0db74aef5456d7bf7e3185ab5ab623ecfe74014893", provider) - - // Deploy in the currrent network and return the Swaplace instance - const Swaplace = await deploy("Swaplace", wallet) - - // Log Contract address, the Tx then return the Contract instance - console.log( - "\nContract %s \nDeployed to %s \nAt Tx %s", - "Swaplace", - Swaplace.address, - Swaplace.deployTransaction.hash - ) -} - -main().catch((error) => { - console.error(error) - process.exitCode = 1 -}) diff --git a/scripts/estimateGasOfEvents.ts b/scripts/estimateGasOfEvents.ts deleted file mode 100644 index e67cb2c..0000000 --- a/scripts/estimateGasOfEvents.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { ethers } from "hardhat"; -import { blocktimestamp } from "../test/utils/utils"; -import { Swap, composeSwap } from "../test/utils/SwapFactory"; -import abi from "../artifacts/contracts/Swaplace.sol/Swaplace.json"; -import { deploy } from "../test/utils/utils"; - -export async function main() { - // Get the first account from the list of accounts - const [signer] = await ethers.getSigners(); - - // Get the Swaplace address from .env file - // const swaplaceAddress: string = process.env.SWAPLACE_ADDRESS || ""; - - // Get the Swaplace instance - // const Swaplace = new ethers.Contract(swaplaceAddress, abi.abi, signer); - - // Deploy in the currrent network and return the Swaplace instance - const Swaplace = await deploy("Swaplace", signer); - - // Fill the Swap struct - const owner = signer.address; - const allowed = ethers.constants.AddressZero; - const expiry = (await blocktimestamp()* 2); - - // Build the biding assets - const bidingAddr = ["0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"]; // USDC - const bidingAmountOrId = [1000]; - - // Build the asking assets - const askingAddr = ["0x2260fac5e5542a773aa44fbcfedf7c193bc2c599"]; // WBTC - const askingAmountOrId = [1]; - - // Compose the swap - const swap: Swap = await composeSwap( - owner, - allowed, - expiry, - bidingAddr, - bidingAmountOrId, - askingAddr, - askingAmountOrId - ); - - // Create the swap - let tx = await Swaplace.createSwap(swap); - - // Wait for the transaction to be mined - // await tx.wait(); - tx = await Swaplace.getGasCost(); - - // Log the transaction hash - console.log("\nGas used 'emit SwapCreated()': ", tx); -} - -main().catch((error) => { - console.error(error); - process.exitCode = 1; -}); - From 0c47ede9aa52019ab089f8b0e8a02d224134f9be Mon Sep 17 00:00:00 2001 From: Joao Victor Pereira Santos Date: Tue, 19 Dec 2023 16:38:57 -0300 Subject: [PATCH 4/7] fix: [ISSUE-119] Unit tests using accept address --- test/TestSwaplace.test.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/TestSwaplace.test.ts b/test/TestSwaplace.test.ts index 2c8e965..3dffd56 100644 --- a/test/TestSwaplace.test.ts +++ b/test/TestSwaplace.test.ts @@ -280,7 +280,7 @@ describe("Swaplace", async function () { ), ) .to.emit(Swaplace, "SwapAccepted") - .withArgs(await Swaplace.totalSwaps(), receiver.address); + .withArgs(await Swaplace.totalSwaps(), acceptee.address); }); it("Should be able to {acceptSwap} as N-N Swap", async function () { @@ -313,7 +313,7 @@ describe("Swaplace", async function () { ), ) .to.emit(Swaplace, "SwapAccepted") - .withArgs(await Swaplace.totalSwaps(), receiver.address); + .withArgs(await Swaplace.totalSwaps(), acceptee.address); }); it("Should be able to {acceptSwap} as P2P Swap", async function () { @@ -337,7 +337,7 @@ describe("Swaplace", async function () { ), ) .to.emit(Swaplace, "SwapAccepted") - .withArgs(await Swaplace.totalSwaps(), receiver.address); + .withArgs(await Swaplace.totalSwaps(), acceptee.address); }); }); @@ -352,7 +352,7 @@ describe("Swaplace", async function () { ), ) .to.emit(Swaplace, "SwapAccepted") - .withArgs(await Swaplace.totalSwaps(), receiver.address); + .withArgs(await Swaplace.totalSwaps(), acceptee.address); await expect( Swaplace.connect(acceptee).acceptSwap( From 213bc1f883feb549e99e6314c3d891827763fb4a Mon Sep 17 00:00:00 2001 From: Joao Victor Pereira Santos Date: Tue, 19 Dec 2023 16:40:44 -0300 Subject: [PATCH 5/7] fix: [ISSUE-119] Remove unecessary files --- estimateGasOfEvents.md | 117 ----------------------------------------- 1 file changed, 117 deletions(-) delete mode 100644 estimateGasOfEvents.md diff --git a/estimateGasOfEvents.md b/estimateGasOfEvents.md deleted file mode 100644 index 371091e..0000000 --- a/estimateGasOfEvents.md +++ /dev/null @@ -1,117 +0,0 @@ -# docs: research gas and cost efficiency for event emission - -## How I calculated the gas usage? - -- Example: - -``` -uint256 startGas = gasleft(); - -// code - -gasUsed = startGas - gasleft(); -``` - -## Prepare a spreadsheet with the gas usage based on the current and proposed events emitted and set for a comparison. - -- In the document I separeted a comparison about the options to emit events :) - -## Estimate the gas when calling createSwap and record their gas usage. - -- When we call the "createSwap" event with the current parameters (id, owner and expiry) the gas usage is 1932. - -``` -event SwapCreated( - uint256 indexed id, - address indexed owner, - uint256 indexed expiry -); -``` - -``` -emit SwapCreated(swapId, msg.sender, swap.expiry); -``` - -- But we can optimize with assembly, so the gas usage can be: 1919 - -``` -//keccak-256(SwapCreated(uint256,address,uint256)) -bytes32 private constant EVENT_SWAP_CREATED_SIGNATURE = - 0xecac413765eac3982e66e569ad3a200e6b3f188ac4d7d44cc5da667779ca8d05; -``` - -``` -uint256 swapExpiry = swap.expiry; -assembly { - log4(0x00, 0x00, EVENT_SWAP_CREATED_SIGNATURE, swapId, caller(), swapExpiry) -} -``` - -## Take measures of the gas usage. - -- I change the emit of events to use assembly to reduce the gas usage. - -## Add the allowed field in the events. Take Measure. - -- Gas usage with Solidity: 2702 - -``` -event SwapCreated( - uint256 indexed id, - address indexed owner, - uint256 indexed expiry, - address allowed -); -``` - -``` -emit SwapCreated(swapId, msg.sender, swap.expiry, swap.allowed); -``` - -- But we can optimize with assembly, so the gas usage can be: 2502 - -``` -//keccak-256(SwapCreated(uint256,address,uint256,address)) -bytes32 private constant EVENT_SWAP_CREATED_SIGNATURE = - 0x43a58bfac3282e5ce3bfd714c5bc0ddff8d6f2cd049db0b02a25d7cdd5026efb; -``` - -``` -uint256 swapExpiry = swap.expiry; -address allowed = swap.allowed; -assembly { - mstore(0x00, allowed) - log4(0x00, 0x20, EVENT_SWAP_CREATED_SIGNATURE, swapId, caller(), swapExpiry) -} -``` - -## Add the bidding and asking field in the events. Take Measure. - -- Gas usage with Solidity: 7646 - -``` -event SwapCreated( - uint256 indexed id, - address indexed owner, - uint256 indexed expiry, - address allowed, - ISwap.Asset[] biding, - ISwap.Asset[] asking -); -``` - -``` -emit SwapCreated(swapId, msg.sender, swap.expiry, swap.allowed, swap.biding, swap.asking); -``` - -## Add the price of ETH at $2.200 and calculate the gas cost in dollars. - -- I don't know how I can make this setting the ETH value. (help me please :) - -# Conclusion - -- After the study about gas usage in the swaplace, I came to the conclusion that we can add the "allowed" field in the "SwapCreated" event, but if we add the "biding" and "asking" fields, we will increase a lot the gas usage in the emit of events, so I this PR I added the "allowed" field in the swap created event and refactored all events to use assembly to reduce the gas usage. - -- And about the "biding" and "asking" fields, I think that is have a lot of gas usage and I'm studying about how we can emit the event with assembly there paramters, I tried but I couldn't, I'm trying yet :) - -- If possible, I need your review about this PR :), I'm ready to fix/improve something and work togheter!!! \ No newline at end of file From 3d17eec428dc59ca278ccaa8ad52102b1af45f14 Mon Sep 17 00:00:00 2001 From: Joao Victor Pereira Santos Date: Tue, 19 Dec 2023 16:42:57 -0300 Subject: [PATCH 6/7] refactor: [ISSUE-119] Format approveToken.ts file --- scripts/approveToken.ts | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/scripts/approveToken.ts b/scripts/approveToken.ts index 63aa195..dd4ca4c 100644 --- a/scripts/approveToken.ts +++ b/scripts/approveToken.ts @@ -1,33 +1,33 @@ -import { ethers } from "hardhat" +import { ethers } from "hardhat"; import { ERC20ABI } from "../test/utils/utils"; export async function main() { - // Get the first account from the list of accounts - const [signer] = await ethers.getSigners(); + // Get the first account from the list of accounts + const [signer] = await ethers.getSigners(); - // Get the Swaplace address from .env file - const swaplaceAddress: string = process.env.SWAPLACE_ADDRESS || ""; + // Get the Swaplace address from .env file + const swaplaceAddress: string = process.env.SWAPLACE_ADDRESS || ""; - // Get the token contract, replace to the token that you want approve - const tokenContract = ''; + // Get the token contract, replace to the token that you want approve + const tokenContract = ""; - // Get the token instance - const Token = new ethers.Contract(tokenContract, ERC20ABI, signer); + // Get the token instance + const Token = new ethers.Contract(tokenContract, ERC20ABI, signer); - // Get the value to approve token, replace to value that you need - const valueApproveToken = BigInt(99999 * (10**18)); - - // Make the approve - const tx = Token.approve(swaplaceAddress, valueApproveToken) + // Get the value to approve token, replace to value that you need + const valueApproveToken = BigInt(99999 * 10 ** 18); - // Wait for the transaction to be mined - await tx.wait(); + // Make the approve + const tx = Token.approve(swaplaceAddress, valueApproveToken); - // Log the transaction hash - console.log("\nTransaction Hash: ", tx); + // Wait for the transaction to be mined + await tx.wait(); + + // Log the transaction hash + console.log("\nTransaction Hash: ", tx); } main().catch((error) => { - console.error(error); - process.exitCode = 1; + console.error(error); + process.exitCode = 1; }); From 70d32bf3acf6b3f894a0e1e8b794dd4a4c61c97d Mon Sep 17 00:00:00 2001 From: Joao Victor Pereira Santos Date: Wed, 3 Jan 2024 20:11:07 -0300 Subject: [PATCH 7/7] fix: remove the scripts that not part of the proposal #119 --- scripts/approveToken.ts | 33 --------------------------------- test/utils/utils.ts | 18 +----------------- 2 files changed, 1 insertion(+), 50 deletions(-) delete mode 100644 scripts/approveToken.ts diff --git a/scripts/approveToken.ts b/scripts/approveToken.ts deleted file mode 100644 index dd4ca4c..0000000 --- a/scripts/approveToken.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { ethers } from "hardhat"; -import { ERC20ABI } from "../test/utils/utils"; - -export async function main() { - // Get the first account from the list of accounts - const [signer] = await ethers.getSigners(); - - // Get the Swaplace address from .env file - const swaplaceAddress: string = process.env.SWAPLACE_ADDRESS || ""; - - // Get the token contract, replace to the token that you want approve - const tokenContract = ""; - - // Get the token instance - const Token = new ethers.Contract(tokenContract, ERC20ABI, signer); - - // Get the value to approve token, replace to value that you need - const valueApproveToken = BigInt(99999 * 10 ** 18); - - // Make the approve - const tx = Token.approve(swaplaceAddress, valueApproveToken); - - // Wait for the transaction to be mined - await tx.wait(); - - // Log the transaction hash - console.log("\nTransaction Hash: ", tx); -} - -main().catch((error) => { - console.error(error); - process.exitCode = 1; -}); diff --git a/test/utils/utils.ts b/test/utils/utils.ts index 4f6b30c..832fe75 100644 --- a/test/utils/utils.ts +++ b/test/utils/utils.ts @@ -30,23 +30,7 @@ export async function deploy(contractName: any, signer: any) { return Contract; } -/** - * @dev ABI of ERC20 standard - */ -export const ERC20ABI = [ - "function name() public view returns (string)", - "function symbol() public view returns (string)", - "function decimals() public view returns (uint8)", - "function totalSupply() public view returns (uint256)", - "function balanceOf(address _owner) public view returns (uint256 balance)", - "function transfer(address _to, uint256 _value) public returns (bool success)", - "function transferFrom(address _from, address _to, uint256 _value) public returns (bool success)", - "function approve(address _spender, uint256 _value) public returns (bool success)", - "function allowance(address _owner, address _spender) public view returns (uint256 remaining)", -]; - module.exports = { blocktimestamp, - deploy, - ERC20ABI, + deploy };