This repository has been archived by the owner on Apr 30, 2024. It is now read-only.
generated from storyprotocol/solidity-template
-
Notifications
You must be signed in to change notification settings - Fork 108
Token Withdrawal Module for token withdrawals on behalf of IPAccount #131
Merged
Merged
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
54076e0
feat: Token Management Module for token transfers on behalf of IPAcco…
jdubpark 9581a9f
fix: amount calculation for transfer
jdubpark f7d9e86
nit: comments
jdubpark 1ef7b41
style: lint
jdubpark 231864e
feat: ERC Withdrawal module with restriction on receiver as IPA owner
jdubpark File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
43 changes: 43 additions & 0 deletions
43
contracts/interfaces/modules/external/ITokenWithdrawalModule.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.23; | ||
|
||
import { IModule } from "../base/IModule.sol"; | ||
|
||
/// @title Token Management Module | ||
/// @notice Module for transferring ERC20, ERC721, and ERC1155 tokens for IP Accounts. | ||
/// @dev SECURITY RISK: An IPAccount can delegate to a frontend contract (not a registered module) to transfer tokens | ||
/// on behalf of the IPAccount via the Token Management Module. This frontend contract can transfer any tokens that are | ||
/// approved by the IPAccount for the Token Management Module. In other words, there's no mechanism for this module to | ||
/// granularly control which token a caller (approved contract in this case) can transfer. | ||
interface ITokenWithdrawalModule is IModule { | ||
/// @notice Withdraws ERC20 token from the IP account to the IP account owner. | ||
/// @dev When calling this function, the caller must have the permission to call `transfer` via the IP account. | ||
/// @dev Does not support transfer of multiple tokens at once. | ||
/// @param ipAccount The IP account to transfer the ERC20 token from | ||
/// @param tokenContract The address of the ERC20 token contract | ||
/// @param amount The amount of token to transfer | ||
function withdrawERC20(address payable ipAccount, address tokenContract, uint256 amount) external; | ||
|
||
/// @notice Withdraws ERC721 token from the IP account to the IP account owner. | ||
/// @dev When calling this function, the caller must have the permission to call `transferFrom` via the IP account. | ||
/// @dev Does not support batch transfers. | ||
/// @param ipAccount The IP account to transfer the ERC721 token from | ||
/// @param tokenContract The address of the ERC721 token contract | ||
/// @param tokenId The ID of the token to transfer | ||
function withdrawERC721(address payable ipAccount, address tokenContract, uint256 tokenId) external; | ||
|
||
/// @notice Withdraws ERC1155 token from the IP account to the IP account owner. | ||
/// @dev When calling this function, the caller must have the permission to call `safeTransferFrom` via the IP | ||
/// account. | ||
/// @dev Does not support batch transfers. | ||
/// @param ipAccount The IP account to transfer the ERC1155 token from | ||
/// @param tokenContract The address of the ERC1155 token contract | ||
/// @param tokenId The ID of the token to transfer | ||
/// @param amount The amount of token to transfer | ||
function withdrawERC1155( | ||
address payable ipAccount, | ||
address tokenContract, | ||
uint256 tokenId, | ||
uint256 amount | ||
) external; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.23; | ||
|
||
import { ERC165Checker } from "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol"; | ||
|
||
import { IIPAccount } from "../../interfaces/IIPAccount.sol"; | ||
import { IIPAccountRegistry } from "../../interfaces/registries/IIPAccountRegistry.sol"; | ||
import { ITokenWithdrawalModule } from "../../interfaces/modules/external/ITokenWithdrawalModule.sol"; | ||
import { IPAccountChecker } from "../../lib/registries/IPAccountChecker.sol"; | ||
import { TOKEN_WITHDRAWAL_MODULE_KEY } from "../../lib/modules/Module.sol"; | ||
import { BaseModule } from "../BaseModule.sol"; | ||
import { AccessControlled } from "../../access/AccessControlled.sol"; | ||
|
||
/// @title Token Management Module | ||
/// @notice Module for transferring ERC20, ERC721, and ERC1155 tokens for IP Accounts. | ||
/// @dev SECURITY RISK: An IPAccount can delegate to a frontend contract (not a registered module) to transfer tokens | ||
/// on behalf of the IPAccount via the Token Management Module. This frontend contract can transfer any tokens that are | ||
/// approved by the IPAccount for the Token Management Module. In other words, there's no mechanism for this module to | ||
/// granularly control which token a caller (approved contract in this case) can transfer. | ||
contract TokenWithdrawalModule is AccessControlled, BaseModule, ITokenWithdrawalModule { | ||
using ERC165Checker for address; | ||
using IPAccountChecker for IIPAccountRegistry; | ||
|
||
string public constant override name = TOKEN_WITHDRAWAL_MODULE_KEY; | ||
|
||
constructor( | ||
address accessController, | ||
address ipAccountRegistry | ||
) AccessControlled(accessController, ipAccountRegistry) {} | ||
|
||
/// @notice Withdraws ERC20 token from the IP account to the IP account owner. | ||
/// @dev When calling this function, the caller must have the permission to call `transfer` via the IP account. | ||
/// @dev Does not support transfer of multiple tokens at once. | ||
/// @param ipAccount The IP account to transfer the ERC20 token from | ||
/// @param tokenContract The address of the ERC20 token contract | ||
/// @param amount The amount of token to transfer | ||
function withdrawERC20( | ||
address payable ipAccount, | ||
address tokenContract, | ||
uint256 amount | ||
) external verifyPermission(ipAccount) { | ||
IIPAccount(ipAccount).execute( | ||
tokenContract, | ||
0, | ||
abi.encodeWithSignature("transfer(address,uint256)", IIPAccount(ipAccount).owner(), amount) | ||
); | ||
} | ||
|
||
/// @notice Withdraws ERC721 token from the IP account to the IP account owner. | ||
/// @dev When calling this function, the caller must have the permission to call `transferFrom` via the IP account. | ||
/// @dev Does not support batch transfers. | ||
/// @param ipAccount The IP account to transfer the ERC721 token from | ||
/// @param tokenContract The address of the ERC721 token contract | ||
/// @param tokenId The ID of the token to transfer | ||
function withdrawERC721( | ||
address payable ipAccount, | ||
address tokenContract, | ||
uint256 tokenId | ||
) external verifyPermission(ipAccount) { | ||
IIPAccount(ipAccount).execute( | ||
tokenContract, | ||
0, | ||
abi.encodeWithSignature( | ||
"transferFrom(address,address,uint256)", | ||
ipAccount, | ||
IIPAccount(ipAccount).owner(), | ||
tokenId | ||
) | ||
); | ||
} | ||
|
||
/// @notice Withdraws ERC1155 token from the IP account to the IP account owner. | ||
/// @dev When calling this function, the caller must have the permission to call `safeTransferFrom` via the IP | ||
/// account. | ||
/// @dev Does not support batch transfers. | ||
/// @param ipAccount The IP account to transfer the ERC1155 token from | ||
/// @param tokenContract The address of the ERC1155 token contract | ||
/// @param tokenId The ID of the token to transfer | ||
/// @param amount The amount of token to transfer | ||
function withdrawERC1155( | ||
address payable ipAccount, | ||
address tokenContract, | ||
uint256 tokenId, | ||
uint256 amount | ||
) external verifyPermission(ipAccount) { | ||
IIPAccount(ipAccount).execute( | ||
tokenContract, | ||
0, | ||
abi.encodeWithSignature( | ||
"safeTransferFrom(address,address,uint256,uint256,bytes)", | ||
ipAccount, | ||
IIPAccount(ipAccount).owner(), | ||
tokenId, | ||
amount, | ||
"" | ||
) | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to keep the
MockTokenManagementModule
, the TokenWithdrawalModule` will be moved to the periphery repo. And we should cover such tests in core repo.