diff --git a/.gitmodules b/.gitmodules index 5c6b89f7..bf4ea1cf 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "contracts/lib/chainlink-brownie-contracts"] path = contracts/lib/chainlink-brownie-contracts url = https://github.com/smartcontractkit/chainlink-brownie-contracts +[submodule "contracts/lib/openzeppelin-contracts"] + path = contracts/lib/openzeppelin-contracts + url = https://github.com/OpenZeppelin/openzeppelin-contracts diff --git a/contracts/.env.example b/contracts/.env.example deleted file mode 100644 index 8b137891..00000000 --- a/contracts/.env.example +++ /dev/null @@ -1 +0,0 @@ - diff --git a/contracts/foundry.lock b/contracts/foundry.lock index eef3d685..ec195333 100644 --- a/contracts/foundry.lock +++ b/contracts/foundry.lock @@ -1,5 +1,11 @@ { "lib/forge-std": { "rev": "3b20d60d14b343ee4f908cb8079495c07f5e8981" + }, + "lib\\openzeppelin-contracts": { + "tag": { + "name": "v5.5.0", + "rev": "fcbae5394ae8ad52d8e580a3477db99814b9d565" + } } } \ No newline at end of file diff --git a/contracts/foundry.toml b/contracts/foundry.toml index 64d81706..6f0d7112 100644 --- a/contracts/foundry.toml +++ b/contracts/foundry.toml @@ -2,6 +2,7 @@ src = "src" out = "out" libs = ["lib"] -solc_version = '0.8.13' +solc_version = '0.8.20' + remappings = ['@openzeppelin/=lib/openzeppelin-contracts/'] # See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options # forge create --rpc-url https://eth-sepolia.g.alchemy.com/v2/nnY0qPUQLYsUvb5BKJM5bh81sI6O0PQG --private-key fba7342ef6879df2c735644c734ea69c140f423d84eb2d53fbdfd53fd5d7c586 src/Token.sol:MyToken --legacy \ No newline at end of file diff --git a/contracts/lib/openzeppelin-contracts b/contracts/lib/openzeppelin-contracts new file mode 160000 index 00000000..fcbae539 --- /dev/null +++ b/contracts/lib/openzeppelin-contracts @@ -0,0 +1 @@ +Subproject commit fcbae5394ae8ad52d8e580a3477db99814b9d565 diff --git a/contracts/src/Chainvoice.sol b/contracts/src/Chainvoice.sol index 042397b4..63e9e6df 100644 --- a/contracts/src/Chainvoice.sol +++ b/contracts/src/Chainvoice.sol @@ -1,15 +1,14 @@ // SPDX-License-Identifier: Unlicense -pragma solidity ^0.8.13; +pragma solidity ^0.8.20; + + +import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -interface IERC20 { - function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); - function balanceOf(address account) external view returns (uint256); - function allowance(address owner, address spender) external view returns (uint256); -} contract Chainvoice { - // ========== Errors ========== - // Existing + using SafeERC20 for IERC20; + // Errors error MixedTokenBatch(); error InvalidBatchSize(); error AlreadySettled(); @@ -103,16 +102,6 @@ contract Chainvoice { // Constants uint256 public constant MAX_BATCH = 50; - // ========== Internal Utils ========== - function _isERC20(address token) internal view returns (bool) { - if (token == address(0)) return false; - if (token.code.length == 0) return false; - (bool success, ) = token.staticcall( - abi.encodeWithSignature("balanceOf(address)", address(this)) - ); - return success; - } - // ========== Single-invoice create ========== function createInvoice( address to, @@ -258,12 +247,11 @@ contract Chainvoice { } accumulatedFees += fee; - bool transferSuccess = IERC20(invoice.tokenAddress).transferFrom( + IERC20(invoice.tokenAddress).safeTransferFrom( msg.sender, invoice.from, invoice.amountDue ); - if (!transferSuccess) revert TokenTransferFailed(); } emit InvoicePaid( @@ -331,8 +319,7 @@ contract Chainvoice { for (uint256 i = 0; i < n; i++) { InvoiceDetails storage inv = invoices[invoiceIds[i]]; - bool ok = erc20.transferFrom(msg.sender, inv.from, inv.amountDue); - if (!ok) revert TokenTransferFailed(); + erc20.safeTransferFrom(msg.sender, inv.from, inv.amountDue); emit InvoicePaid(inv.id, inv.from, inv.to, inv.amountDue, token); } } diff --git a/contracts/test/Chainvoice.t.sol b/contracts/test/Chainvoice.t.sol index 2abb1ce9..23753d01 100644 --- a/contracts/test/Chainvoice.t.sol +++ b/contracts/test/Chainvoice.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: Unlicense -pragma solidity ^0.8.13; +pragma solidity ^0.8.20; import {Test} from "forge-std/Test.sol"; import {console} from "forge-std/console.sol";