diff --git a/.gas-snapshot b/.gas-snapshot deleted file mode 100644 index b9e6cae..0000000 --- a/.gas-snapshot +++ /dev/null @@ -1,84 +0,0 @@ -ERC1155STest:testApprovalForAllWithTransferSingle() (gas: 99244) -ERC1155STest:testFailNotEnoughSingleAllowance() (gas: 44397) -ERC1155STest:testSafeBatchTransferFrom() (gas: 187898) -ERC1155STest:testSetApprovalForOne() (gas: 58177) -ERC1155STest:testSingleAllowanceIncrease() (gas: 82527) -ERC1155STest:testTokenURI() (gas: 8442) -ERC1155Test:testApproveAll() (gas: 31275) -ERC1155Test:testApproveAll(address,bool) (runs: 256, μ: 17171, ~: 11661) -ERC1155Test:testBatchBalanceOf() (gas: 159126) -ERC1155Test:testBatchBalanceOf(address[],uint256[],uint256[],bytes) (runs: 256, μ: 3331505, ~: 2614937) -ERC1155Test:testBatchBurn() (gas: 152184) -ERC1155Test:testBatchBurn(address,uint256[],uint256[],uint256[],bytes) (runs: 256, μ: 3481310, ~: 3070785) -ERC1155Test:testBatchMintToEOA() (gas: 138146) -ERC1155Test:testBatchMintToEOA(address,uint256[],uint256[],bytes) (runs: 256, μ: 3288332, ~: 2967840) -ERC1155Test:testBatchMintToERC1155Recipient() (gas: 918093) -ERC1155Test:testBatchMintToERC1155Recipient(uint256[],uint256[],bytes) (runs: 256, μ: 7287688, ~: 6309122) -ERC1155Test:testBurn() (gas: 39050) -ERC1155Test:testBurn(address,uint256,uint256,bytes,uint256) (runs: 256, μ: 40523, ~: 42586) -ERC1155Test:testFailBalanceOfBatchWithArrayMismatch() (gas: 8188) -ERC1155Test:testFailBalanceOfBatchWithArrayMismatch(address[],uint256[]) (runs: 256, μ: 56461, ~: 57231) -ERC1155Test:testFailBatchBurnInsufficientBalance() (gas: 136638) -ERC1155Test:testFailBatchBurnInsufficientBalance(address,uint256[],uint256[],uint256[],bytes) (runs: 256, μ: 1287411, ~: 442468) -ERC1155Test:testFailBatchBurnWithArrayLengthMismatch() (gas: 136066) -ERC1155Test:testFailBatchBurnWithArrayLengthMismatch(address,uint256[],uint256[],uint256[],bytes) (runs: 256, μ: 77457, ~: 79066) -ERC1155Test:testFailBatchMintToNonERC1155Recipient() (gas: 175888) -ERC1155Test:testFailBatchMintToNonERC1155Recipient(uint256[],uint256[],bytes) (runs: 256, μ: 3160423, ~: 2688902) -ERC1155Test:testFailBatchMintToRevertingERC1155Recipient() (gas: 331370) -ERC1155Test:testFailBatchMintToRevertingERC1155Recipient(uint256[],uint256[],bytes) (runs: 256, μ: 3315929, ~: 2844407) -ERC1155Test:testFailBatchMintToWrongReturnDataERC1155Recipient() (gas: 302076) -ERC1155Test:testFailBatchMintToWrongReturnDataERC1155Recipient(uint256[],uint256[],bytes) (runs: 256, μ: 3286656, ~: 2815134) -ERC1155Test:testFailBatchMintToZero() (gas: 132144) -ERC1155Test:testFailBatchMintToZero(uint256[],uint256[],bytes) (runs: 256, μ: 3090845, ~: 2617992) -ERC1155Test:testFailBatchMintWithArrayMismatch() (gas: 9802) -ERC1155Test:testFailBatchMintWithArrayMismatch(address,uint256[],uint256[],bytes) (runs: 256, μ: 69542, ~: 69109) -ERC1155Test:testFailBurnInsufficientBalance() (gas: 35155) -ERC1155Test:testFailBurnInsufficientBalance(address,uint256,uint256,uint256,bytes) (runs: 256, μ: 36289, ~: 38573) -ERC1155Test:testFailMintToNonERC155Recipient() (gas: 76673) -ERC1155Test:testFailMintToNonERC155Recipient(uint256,uint256,bytes) (runs: 256, μ: 76882, ~: 77571) -ERC1155Test:testFailMintToRevertingERC155Recipient() (gas: 231870) -ERC1155Test:testFailMintToRevertingERC155Recipient(uint256,uint256,bytes) (runs: 256, μ: 232076, ~: 232765) -ERC1155Test:testFailMintToWrongReturnDataERC155Recipient() (gas: 231846) -ERC1155Test:testFailMintToWrongReturnDataERC155Recipient(uint256,uint256,bytes) (runs: 256, μ: 232078, ~: 232767) -ERC1155Test:testFailMintToZero() (gas: 33954) -ERC1155Test:testFailMintToZero(uint256,uint256,bytes) (runs: 256, μ: 33956, ~: 34764) -ERC1155Test:testFailSafeBatchTransferFromToNonERC1155Recipient() (gas: 330694) -ERC1155Test:testFailSafeBatchTransferFromToNonERC1155Recipient(uint256[],uint256[],uint256[],bytes,bytes) (runs: 256, μ: 3526734, ~: 2980903) -ERC1155Test:testFailSafeBatchTransferFromToRevertingERC1155Recipient() (gas: 486181) -ERC1155Test:testFailSafeBatchTransferFromToRevertingERC1155Recipient(uint256[],uint256[],uint256[],bytes,bytes) (runs: 256, μ: 3682305, ~: 3136470) -ERC1155Test:testFailSafeBatchTransferFromToWrongReturnDataERC1155Recipient() (gas: 456807) -ERC1155Test:testFailSafeBatchTransferFromToWrongReturnDataERC1155Recipient(uint256[],uint256[],uint256[],bytes,bytes) (runs: 256, μ: 3652880, ~: 3107047) -ERC1155Test:testFailSafeBatchTransferFromToZero() (gas: 287669) -ERC1155Test:testFailSafeBatchTransferFromToZero(uint256[],uint256[],uint256[],bytes,bytes) (runs: 256, μ: 3483272, ~: 2937544) -ERC1155Test:testFailSafeBatchTransferFromWithArrayLengthMismatch() (gas: 163496) -ERC1155Test:testFailSafeBatchTransferFromWithArrayLengthMismatch(address,uint256[],uint256[],uint256[],bytes,bytes) (runs: 256, μ: 81492, ~: 82342) -ERC1155Test:testFailSafeBatchTransferInsufficientBalance() (gas: 164339) -ERC1155Test:testFailSafeBatchTransferInsufficientBalance(address,uint256[],uint256[],uint256[],bytes,bytes) (runs: 256, μ: 1507251, ~: 501488) -ERC1155Test:testFailSafeTransferFromInsufficientBalance() (gas: 66242) -ERC1155Test:testFailSafeTransferFromInsufficientBalance(address,uint256,uint256,uint256,bytes,bytes) (runs: 256, μ: 66861, ~: 70389) -ERC1155Test:testFailSafeTransferFromSelfInsufficientBalance() (gas: 37236) -ERC1155Test:testFailSafeTransferFromSelfInsufficientBalance(address,uint256,uint256,uint256,bytes,bytes) (runs: 256, μ: 38967, ~: 41318) -ERC1155Test:testFailSafeTransferFromToNonERC155Recipient() (gas: 107738) -ERC1155Test:testFailSafeTransferFromToNonERC155Recipient(uint256,uint256,uint256,bytes,bytes) (runs: 256, μ: 107707, ~: 111706) -ERC1155Test:testFailSafeTransferFromToRevertingERC1155Recipient() (gas: 262890) -ERC1155Test:testFailSafeTransferFromToRevertingERC1155Recipient(uint256,uint256,uint256,bytes,bytes) (runs: 256, μ: 262829, ~: 266829) -ERC1155Test:testFailSafeTransferFromToWrongReturnDataERC1155Recipient() (gas: 233482) -ERC1155Test:testFailSafeTransferFromToWrongReturnDataERC1155Recipient(uint256,uint256,uint256,bytes,bytes) (runs: 256, μ: 233399, ~: 237398) -ERC1155Test:testFailSafeTransferFromToZero() (gas: 64991) -ERC1155Test:testFailSafeTransferFromToZero(uint256,uint256,uint256,bytes,bytes) (runs: 256, μ: 65093, ~: 69017) -ERC1155Test:testMintToEOA() (gas: 35094) -ERC1155Test:testMintToEOA(address,uint256,uint256,bytes) (runs: 256, μ: 35611, ~: 36230) -ERC1155Test:testMintToERC1155Recipient() (gas: 583051) -ERC1155Test:testMintToERC1155Recipient(uint256,uint256,bytes) (runs: 256, μ: 612712, ~: 606035) -ERC1155Test:testSafeBatchTransferFromToEOA() (gas: 299697) -ERC1155Test:testSafeBatchTransferFromToEOA(address,uint256[],uint256[],uint256[],bytes,bytes) (runs: 256, μ: 4772687, ~: 3804841) -ERC1155Test:testSafeBatchTransferFromToERC1155Recipient() (gas: 1098785) -ERC1155Test:testSafeBatchTransferFromToERC1155Recipient(uint256[],uint256[],uint256[],bytes,bytes) (runs: 256, μ: 7660296, ~: 6527397) -ERC1155Test:testSafeTransferFromSelf() (gas: 67349) -ERC1155Test:testSafeTransferFromSelf(uint256,uint256,bytes,uint256,address,bytes) (runs: 256, μ: 67874, ~: 71758) -ERC1155Test:testSafeTransferFromToEOA() (gas: 96491) -ERC1155Test:testSafeTransferFromToEOA(uint256,uint256,bytes,uint256,address,bytes) (runs: 256, μ: 96965, ~: 100785) -ERC1155Test:testSafeTransferFromToERC1155Recipient() (gas: 664240) -ERC1155Test:testSafeTransferFromToERC1155Recipient(uint256,uint256,bytes,uint256,bytes) (runs: 256, μ: 694413, ~: 690341) -PositionsSplitterTest:testWrapUnwrap() (gas: 884105) -PositionsSplitterTest:testWrapperAlreadyRegistered() (gas: 763172) \ No newline at end of file diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index c1153b8..d650918 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -25,27 +25,6 @@ jobs: # make fuzzing semi-deterministic to avoid noisy gas cost estimation # due to non-deterministic fuzzing (but still use pseudo-random fuzzing seeds) FOUNDRY_FUZZ_SEED: 0x${{ github.event.pull_request.base.sha || github.sha }} - snapshot: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - with: - submodules: recursive - - uses: foundry-rs/foundry-toolchain@v1 - with: - version: nightly - - name: dependencies - run: forge install - - name: check contract sizes - run: forge build --sizes - - name: check gas snapshots - run: forge snapshot --check - env: - # make fuzzing semi-deterministic to avoid noisy gas cost estimation - # due to non-deterministic fuzzing (but still use pseudo-random fuzzing seeds) - FOUNDRY_FUZZ_SEED: 0x${{ github.event.pull_request.base.sha || github.sha }} - - # slither: # runs-on: ubuntu-latest # steps: diff --git a/src/interfaces/IPositionsSplitter.sol b/src/interfaces/IPositionsSplitter.sol deleted file mode 100644 index 4f3e700..0000000 --- a/src/interfaces/IPositionsSplitter.sol +++ /dev/null @@ -1,32 +0,0 @@ -/// SPDX-License-Identifier: Apache-2.0 -pragma solidity 0.8.19; - -interface IPositionsSplitter { - /// @notice id given here needs to be the same as id on Source! - /// @dev Make sure its set for existing ids only - /// @dev Ideally, this should be only called by SuperPositions (or other privileged contract) - /// @param id id of the ERC1155 to wrap - /// @param name name of the ERC20 to create - /// @param symbol symbol of the ERC20 to create - /// @param decimals decimals of the ERC20 to create - function registerWrapper( - uint256 id, - string memory name, - string memory symbol, - uint8 decimals - ) external returns (address); - - /// @notice Use ERC1155 BatchTransfer to wrap multiple ERC1155 ids into separate ERC20 - /// Easier to wrap than to wrapBack because of ERC1155 beauty! - /// @param ids ids of the ERC1155s to wrap - /// @param amounts amounts of the ERC1155s to wrap - function wrapBatch(uint256[] memory ids, uint256[] memory amounts) external; - - /// @param id id of the ERC20s to wrap - /// @param amount amount of the ERC20s to wrap - function wrap(uint256 id, uint256 amount) external; - - /// @param id id of the ERC20s to unwrap - /// @param amount amount of the ERC20s to unwrap - function unwrap(uint256 id, uint256 amount) external; -} diff --git a/src/interfaces/ITransmuter.sol b/src/interfaces/ITransmuter.sol new file mode 100644 index 0000000..70c3ba6 --- /dev/null +++ b/src/interfaces/ITransmuter.sol @@ -0,0 +1,32 @@ +/// SPDX-License-Identifier: Apache-2.0 +pragma solidity 0.8.19; + +interface ITransmuter { + /// @notice id given here needs to be the same as id on Source! + /// @dev Make sure its set for existing ids only + /// @dev Ideally, this should be only called by SuperPositions (or other privileged contract) + /// @param id id of the ERC1155 to wrap + /// @param name name of the ERC20 to create + /// @param symbol symbol of the ERC20 to create + /// @param decimals decimals of the ERC20 to create + function registerTransmuter( + uint256 id, + string memory name, + string memory symbol, + uint8 decimals + ) external returns (address); + + /// @notice Use ERC1155 BatchTransfer to transmute multiple ERC1155 ids into separate ERC20 + /// Easier to transmute to 1155s than to transmute back to erc20 because of ERC1155 beauty! + /// @param ids ids of the ERC1155s to transmute + /// @param amounts amounts of the ERC1155s to transmute + function transmuteBatchToERC20(uint256[] memory ids, uint256[] memory amounts) external; + + /// @param id id of the ERC20s to transmute to erc20 + /// @param amount amount of the ERC20s to transmute to erc20 + function transmuteToERC20(uint256 id, uint256 amount) external; + + /// @param id id of the ERC20s to transmute to erc1155 + /// @param amount amount of the ERC20s to transmute to erc1155 + function transmuteToERC1155s(uint256 id, uint256 amount) external; +} diff --git a/src/test/PostionsSplitter.t.sol b/src/test/PostionsSplitter.t.sol deleted file mode 100644 index 6a41eee..0000000 --- a/src/test/PostionsSplitter.t.sol +++ /dev/null @@ -1,57 +0,0 @@ -/// SPDX-License-Identifier: Apache-2.0 -pragma solidity 0.8.19; - -import "forge-std/Test.sol"; -import {PositionsSplitter} from "../splitter/PositionsSplitter.sol"; -import {MockERC1155s} from "./mocks/MockERC1155s.sol"; -import {ERC20} from "solmate/tokens/ERC20.sol"; -import {sERC20} from "../splitter/sERC20.sol"; - -contract PositionsSplitterTest is Test { - uint256 public constant THOUSAND_E18 = 1000 ether; - - MockERC1155s public superPositions; - PositionsSplitter public positionsSplitter; - ERC20 public syntheticERC20Token; - - address public alice = address(0x2137); - address public bob = address(0x0997); - - function setUp() public { - superPositions = new MockERC1155s(); - superPositions.mint(alice, 1, THOUSAND_E18, ""); - - positionsSplitter = new PositionsSplitter(superPositions); - } - - function testWrapUnwrap() public { - syntheticERC20Token = sERC20(positionsSplitter.registerWrapper(1, "SuperPosition Id 1", "SS1", 18)); - - vm.startPrank(alice); - - superPositions.setApprovalForAll(address(positionsSplitter), true); - positionsSplitter.wrap(1, THOUSAND_E18); - assertEq(superPositions.balanceOf(alice, 1), 0); - assertEq(superPositions.balanceOf(address(positionsSplitter), 1), THOUSAND_E18); - - assertEq(syntheticERC20Token.balanceOf(alice), THOUSAND_E18); - - uint256 sERC20Balance = syntheticERC20Token.balanceOf(alice); - - syntheticERC20Token.approve(address(positionsSplitter), sERC20Balance); - - /// NOTE: Test if 1:1 between 1155 and 20 always holds - positionsSplitter.unwrap(1, sERC20Balance); - - assertEq(superPositions.balanceOf(alice, 1), THOUSAND_E18); - - assertEq(syntheticERC20Token.balanceOf(address(positionsSplitter)), 0); - } - - function testWrapperAlreadyRegistered() public { - syntheticERC20Token = sERC20(positionsSplitter.registerWrapper(1, "SuperPosition Id 1", "SS1", 18)); - - vm.expectRevert(); - syntheticERC20Token = sERC20(positionsSplitter.registerWrapper(1, "SuperPosition Id 1", "SS1", 18)); - } -} diff --git a/src/test/Transmuter.t.sol b/src/test/Transmuter.t.sol new file mode 100644 index 0000000..c47fcc2 --- /dev/null +++ b/src/test/Transmuter.t.sol @@ -0,0 +1,57 @@ +/// SPDX-License-Identifier: Apache-2.0 +pragma solidity 0.8.19; + +import "forge-std/Test.sol"; +import {Transmuter} from "../transmuter/Transmuter.sol"; +import {MockERC1155s} from "./mocks/MockERC1155s.sol"; +import {ERC20} from "solmate/tokens/ERC20.sol"; +import {sERC20} from "../transmuter/sERC20.sol"; + +contract TransmuterTest is Test { + uint256 public constant THOUSAND_E18 = 1000 ether; + + MockERC1155s public superPositions; + Transmuter public transmuter; + ERC20 public syntheticERC20Token; + + address public alice = address(0x2137); + address public bob = address(0x0997); + + function setUp() public { + superPositions = new MockERC1155s(); + superPositions.mint(alice, 1, THOUSAND_E18, ""); + + transmuter = new Transmuter(superPositions); + } + + function testTransmute() public { + syntheticERC20Token = sERC20(transmuter.registerTransmuter(1, "SuperPosition Id 1", "SS1", 18)); + + vm.startPrank(alice); + + superPositions.setApprovalForAll(address(transmuter), true); + transmuter.transmuteToERC20(1, THOUSAND_E18); + assertEq(superPositions.balanceOf(alice, 1), 0); + assertEq(superPositions.balanceOf(address(transmuter), 1), THOUSAND_E18); + + assertEq(syntheticERC20Token.balanceOf(alice), THOUSAND_E18); + + uint256 sERC20Balance = syntheticERC20Token.balanceOf(alice); + + syntheticERC20Token.approve(address(transmuter), sERC20Balance); + + /// NOTE: Test if 1:1 between 1155 and 20 always holds + transmuter.transmuteToERC1155s(1, sERC20Balance); + + assertEq(superPositions.balanceOf(alice, 1), THOUSAND_E18); + + assertEq(syntheticERC20Token.balanceOf(address(transmuter)), 0); + } + + function testTransmuterAlreadyRegistered() public { + syntheticERC20Token = sERC20(transmuter.registerTransmuter(1, "SuperPosition Id 1", "SS1", 18)); + + vm.expectRevert(); + syntheticERC20Token = sERC20(transmuter.registerTransmuter(1, "SuperPosition Id 1", "SS1", 18)); + } +} diff --git a/src/splitter/PositionsSplitter.sol b/src/transmuter/Transmuter.sol similarity index 64% rename from src/splitter/PositionsSplitter.sol rename to src/transmuter/Transmuter.sol index c7a982b..f0b7284 100644 --- a/src/splitter/PositionsSplitter.sol +++ b/src/transmuter/Transmuter.sol @@ -3,35 +3,34 @@ pragma solidity 0.8.19; import {IERC1155s} from "../interfaces/IERC1155s.sol"; import {sERC20} from "./sERC20.sol"; -import {IPositionsSplitter} from "../interfaces/IPositionsSplitter.sol"; +import {ITransmuter} from "../interfaces/ITransmuter.sol"; -/// @title Positions Splitter +/// @title Transmuter /// @author Zeropoint Labs. -/// @dev allows users to split all or individual ids of ERC1155s into ERC20 -contract PositionsSplitter is IPositionsSplitter { +/// @dev allows users to transmute all or individual ids of ERC1155s into synthetic ERC20s +contract Transmuter is ITransmuter { IERC1155s public immutable sERC1155; - event Wrapped(address user, uint256 id, uint256 amount); - event WrappedBatch(address user, uint256[] ids, uint256[] amounts); - event Unwrapped(address user, uint256 id, uint256 amount); + event TransmutedToERC20(address user, uint256 id, uint256 amount); + event TransmutedBatchToERC20(address user, uint256[] ids, uint256[] amounts); + event TransmutedToERC1155s(address user, uint256 id, uint256 amount); - error WRAPPER_ALREADY_REGISTERED(); + error TRANSMUTER_ALREADY_REGISTERED(); - /// @dev id => wrappedERC1155idERC20 mapping(uint256 id => address syntheticToken) public synthethicTokenId; constructor(IERC1155s erc1155s) { sERC1155 = erc1155s; } - /// @inheritdoc IPositionsSplitter - function registerWrapper( + /// @inheritdoc ITransmuter + function registerTransmuter( uint256 id, string memory name, string memory symbol, uint8 decimals ) external override returns (address) { - if (synthethicTokenId[id] != address(0)) revert WRAPPER_ALREADY_REGISTERED(); + if (synthethicTokenId[id] != address(0)) revert TRANSMUTER_ALREADY_REGISTERED(); address syntheticToken = address(new sERC20(name, symbol, decimals)); synthethicTokenId[id] = syntheticToken; @@ -43,23 +42,19 @@ contract PositionsSplitter is IPositionsSplitter { MULTIPLE ID OPERATIONS //////////////////////////////////////////////////////////////*/ - /// @inheritdoc IPositionsSplitter - function wrapBatch(uint256[] memory ids, uint256[] memory amounts) external override { + /// @inheritdoc ITransmuter + function transmuteBatchToERC20(uint256[] memory ids, uint256[] memory amounts) external override { /// @dev Use ERC1155 BatchTransfer to lower costs sERC1155.safeBatchTransferFrom(msg.sender, address(this), ids, amounts, ""); - // Note: Hook to SuperRouter, optional if we want to do something there - // Note: Maybe relevant in future for omnichain-token - // sERC1155.unwrap(msg.sender, ids, amounts); - for (uint256 i = 0; i < ids.length; i++) { sERC20(synthethicTokenId[ids[i]]).mint(msg.sender, amounts[i]); } - emit WrappedBatch(msg.sender, ids, amounts); + emit TransmutedBatchToERC20(msg.sender, ids, amounts); } - /// @notice We are not supporting wrapBack to ERC1155 with multiple ERC20 at once. + /// @notice We are not supporting transmuteBatchToERC1155 with multiple ERC20 at once. /// Note: Its problematic to do so as ERC20 do not support batch ops (in contrary to ERC1155) /// Requires unbouded for loop and within it each allowance check needs to pass /// otherwise, we risk failing in the middle of transaction. @@ -68,22 +63,18 @@ contract PositionsSplitter is IPositionsSplitter { SINGLE ID OPERATIONS //////////////////////////////////////////////////////////////*/ - /// @inheritdoc IPositionsSplitter - function wrap(uint256 id, uint256 amount) external override { + /// @inheritdoc ITransmuter + function transmuteToERC20(uint256 id, uint256 amount) external override { /// @dev singleId approval required for this call to succeed - /// Note: User needs to approve SharesSplitter first + /// Note: User needs to approve Transmuter first sERC1155.safeTransferFrom(msg.sender, address(this), id, amount, ""); - // Note: Hook to SuperRouter, optional if we want to do something there - // Note: Maybe relevant in future for omnichain-token - // sERC1155.unwrap(msg.sender, id, amount); - sERC20(synthethicTokenId[id]).mint(msg.sender, amount); - emit Wrapped(msg.sender, id, amount); + emit TransmutedToERC20(msg.sender, id, amount); } - /// @inheritdoc IPositionsSplitter - function unwrap(uint256 id, uint256 amount) external override { + /// @inheritdoc ITransmuter + function transmuteToERC1155s(uint256 id, uint256 amount) external override { sERC20 token = sERC20(synthethicTokenId[id]); /// @dev No need to transfer to contract, we can burn for msg.sender @@ -97,7 +88,7 @@ contract PositionsSplitter is IPositionsSplitter { sERC1155.safeBatchTransferFrom(address(this), msg.sender, ids, amounts, bytes("")); - emit Unwrapped(msg.sender, id, amount); + emit TransmutedToERC1155s(msg.sender, id, amount); } /*/////////////////////////////////////////////////////////////// diff --git a/src/splitter/sERC20.sol b/src/transmuter/sERC20.sol similarity index 100% rename from src/splitter/sERC20.sol rename to src/transmuter/sERC20.sol