-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
398 additions
and
0 deletions.
There are no files selected for viewing
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,27 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.13; | ||
|
||
interface ISuperToken { | ||
function burn(address user_, uint256 amount_) external; | ||
|
||
function mint(address receiver_, uint256 amount_) external; | ||
|
||
function balanceOf(address account) external; | ||
|
||
function totalSupply() external view returns (uint256); | ||
|
||
function transfer(address to, uint256 value) external returns (bool); | ||
|
||
function approve(address spender, uint256 value) external returns (bool); | ||
|
||
function transferFrom( | ||
address from, | ||
address to, | ||
uint256 value | ||
) external returns (bool); | ||
|
||
function allowance( | ||
address owner, | ||
address spender | ||
) external view returns (uint256); | ||
} |
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,83 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.13; | ||
|
||
import "solady/tokens/ERC20.sol"; | ||
|
||
/** | ||
* @title SuperToken | ||
* @notice An ERC20 contract which enables bridging a token to its sibling chains. | ||
* @dev Implements a custom ERC20 token with minting and burning capabilities restricted to a socket address | ||
*/ | ||
contract SuperToken is ERC20 { | ||
string private _name; | ||
string private _symbol; | ||
uint8 private _decimals; | ||
address public _SOCKET; | ||
|
||
// Custom Errors | ||
error NotSOCKET(); | ||
|
||
modifier onlySOCKET() { | ||
if (msg.sender != _SOCKET) revert NotSOCKET(); | ||
_; | ||
} | ||
|
||
/** | ||
* @notice Initialize the token with name, symbol, and decimals | ||
* @param name_ The name of the token | ||
* @param symbol_ The symbol of the token | ||
* @param decimals_ The number of decimals for the token | ||
* @dev Sets the token parameters and sets the initial socket address to the contract deployer | ||
*/ | ||
constructor(string memory name_, string memory symbol_, uint8 decimals_) { | ||
_name = name_; | ||
_symbol = symbol_; | ||
_decimals = decimals_; | ||
_SOCKET = msg.sender; | ||
} | ||
|
||
/** | ||
* @notice Mint tokens to a specified address | ||
* @dev Can only be called by the SOCKET address | ||
* @param to_ The address to mint tokens to | ||
* @param amount_ The amount of tokens to mint | ||
* @custom:modifier onlySOCKET Ensures only the SOCKET can call this function | ||
*/ | ||
function mint(address to_, uint256 amount_) external onlySOCKET { | ||
_mint(to_, amount_); | ||
} | ||
|
||
/** | ||
* @notice Burn tokens from the caller's balance | ||
* @dev Can only be called by the SOCKET address | ||
* @param amount_ The amount of tokens to burn | ||
* @custom:modifier onlySOCKET Ensures only the SOCKET can call this function | ||
*/ | ||
function burn(uint256 amount_) external onlySOCKET { | ||
_burn(msg.sender, amount_); | ||
} | ||
|
||
/** | ||
* @notice Returns the name of the token | ||
* @return The token's name | ||
*/ | ||
function name() public view override returns (string memory) { | ||
return _name; | ||
} | ||
|
||
/** | ||
* @notice Returns the symbol of the token | ||
* @return The token's symbol | ||
*/ | ||
function symbol() public view override returns (string memory) { | ||
return _symbol; | ||
} | ||
|
||
/** | ||
* @notice Returns the number of decimals for the token | ||
* @return The token's decimal places | ||
*/ | ||
function decimals() public view override returns (uint8) { | ||
return _decimals; | ||
} | ||
} |
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,127 @@ | ||
// SPDX-License-Identifier: Unlicense | ||
pragma solidity ^0.8.13; | ||
|
||
import "socket-protocol/contracts/base/AppGatewayBase.sol"; | ||
import "solady/auth/Ownable.sol"; | ||
import {ISuperToken} from "./ISuperToken.sol"; | ||
|
||
/** | ||
* @title SuperTokenApp | ||
* @notice A cross-chain application for bridging tokens | ||
* @dev Extends AppGatewayBase and Ownable to provide a chain abstracted token bridging functionality | ||
*/ | ||
contract SuperTokenApp is AppGatewayBase, Ownable { | ||
/** | ||
* @notice Counter to track unique transaction IDs | ||
* @dev Incremented with each bridging operation | ||
*/ | ||
uint256 public idCounter; | ||
|
||
/** | ||
* @notice Emitted when a token bridging operation is initiated | ||
* @param asyncId Unique identifier for the asynchronous cross-chain transaction | ||
*/ | ||
event Bridged(bytes32 asyncId); | ||
|
||
/** | ||
* @notice Represents a user's token bridging order | ||
* @dev Contains details of the token transfer across different chains | ||
*/ | ||
struct UserOrder { | ||
/// @notice Source token contract address | ||
address srcToken; | ||
/// @notice Destination token contract address | ||
address dstToken; | ||
/// @notice User initiating the bridge transaction | ||
address user; | ||
/// @notice Amount of tokens to be bridged from source chain | ||
uint256 srcAmount; | ||
/// @notice Deadline for the bridge transaction | ||
uint256 deadline; | ||
} | ||
|
||
/** | ||
* @notice Constructor to initialize the SuperTokenApp | ||
* @param _addressResolver Address of the cross-chain address resolver | ||
* @param deployerContract_ Address of the contract deployer | ||
* @param feesData_ Struct containing fee-related data for bridging | ||
* @dev Sets up the contract, initializes ownership, and configures gateways | ||
*/ | ||
constructor( | ||
address _addressResolver, | ||
address deployerContract_, | ||
FeesData memory feesData_ | ||
) AppGatewayBase(_addressResolver) Ownable() { | ||
_initializeOwner(msg.sender); | ||
addressResolver.setContractsToGateways(deployerContract_); | ||
_setFeesData(feesData_); | ||
} | ||
|
||
/** | ||
* @notice Validates user's token balance for a cross-chain transaction | ||
* @param data Encoded user order and async transaction ID | ||
* @param returnData Balance data returned from the source chain | ||
* @dev Checks if user has sufficient balance to complete the bridge transaction | ||
* @custom:modifier onlyPromises Ensures the function can only be called by the promises system | ||
*/ | ||
function checkBalance( | ||
bytes memory data, | ||
bytes memory returnData | ||
) external onlyPromises { | ||
(UserOrder memory order, bytes32 asyncId) = abi.decode( | ||
data, | ||
(UserOrder, bytes32) | ||
); | ||
|
||
uint256 balance = abi.decode(returnData, (uint256)); | ||
if (balance < order.srcAmount) { | ||
_revertTx(asyncId); | ||
return; | ||
} | ||
} | ||
|
||
/** | ||
* @notice Initiates a cross-chain token bridge transaction | ||
* @param _order Encoded user order details | ||
* @return asyncId Unique identifier for the asynchronous cross-chain transaction | ||
* @dev Handles token bridging logic across different chains | ||
*/ | ||
function bridge( | ||
bytes memory _order | ||
) external async returns (bytes32 asyncId) { | ||
UserOrder memory order = abi.decode(_order, (UserOrder)); | ||
asyncId = _getCurrentAsyncId(); | ||
/* TODO: | ||
1. Check user balance on src chain | ||
2. Check if it was a already deployed contract | ||
if original contract, | ||
transferFrom user to Vault | ||
mint to user on dst chain | ||
if supertoken, | ||
burn from user | ||
transferFrom Vault to user | ||
*/ | ||
|
||
emit Bridged(asyncId); | ||
} | ||
|
||
/** | ||
* @notice Allows the owner to withdraw fee tokens from a specific chain | ||
* @param chainSlug_ Unique identifier of the blockchain | ||
* @param token_ Address of the token to withdraw | ||
* @param amount_ Amount of tokens to withdraw | ||
* @param receiver_ Address receiving the withdrawn tokens | ||
* @dev Restricted to contract owner | ||
* @custom:modifier onlyOwner Ensures only the contract owner can withdraw fees | ||
*/ | ||
function withdrawFeeTokens( | ||
uint32 chainSlug_, | ||
address token_, | ||
uint256 amount_, | ||
address receiver_ | ||
) external onlyOwner { | ||
_withdrawFeeTokens(chainSlug_, token_, amount_, receiver_); | ||
} | ||
|
||
// TODO: Add rescue tokens from Vault in chainSlug | ||
} |
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,68 @@ | ||
// SPDX-License-Identifier: Unlicense | ||
pragma solidity ^0.8.13; | ||
|
||
import "socket-protocol/contracts/base/AppDeployerBase.sol"; | ||
import "solady/auth/Ownable.sol"; | ||
import "./SuperToken.sol"; | ||
|
||
/** | ||
* @title SuperTokenDeployer | ||
* @notice A contract for deploying SuperToken across multiple chains | ||
* @dev Extends AppDeployerBase and Ownable to provide cross-chain token deployment functionality | ||
*/ | ||
contract SuperTokenDeployer is AppDeployerBase, Ownable { | ||
/** | ||
* @notice Unique identifier for the SuperToken contract | ||
* @dev Used to track and manage the SuperToken contract across different chains | ||
*/ | ||
bytes32 public superToken = _createContractId("superToken"); | ||
|
||
/** | ||
* @notice Constructor to initialize the SuperTokenDeployer | ||
* @param addressResolver_ Address of the address resolver contract | ||
* @param owner_ Address of the contract owner | ||
* @param name_ Name of the token to be deployed | ||
* @param symbol_ Symbol of the token to be deployed | ||
* @param decimals_ Number of decimals for the token | ||
* @param feesData_ Struct containing fee-related data for deployment | ||
* @dev Sets up the contract with token creation code and initializes ownership | ||
*/ | ||
constructor( | ||
address addressResolver_, | ||
address owner_, | ||
string memory name_, | ||
string memory symbol_, | ||
uint8 decimals_, | ||
FeesData memory feesData_ | ||
) AppDeployerBase(addressResolver_) Ownable() { | ||
_initializeOwner(owner_); | ||
|
||
creationCodeWithArgs[superToken] = abi.encodePacked( | ||
type(SuperToken).creationCode, | ||
abi.encode(name_, symbol_, decimals_) | ||
); | ||
|
||
_setFeesData(feesData_); | ||
} | ||
|
||
/** | ||
* @notice Deploys the SuperToken contract on a specified chain | ||
* @param chainSlug The unique identifier of the target blockchain | ||
* @dev Triggers the deployment of the SuperToken contract | ||
* @custom:modifier Accessible to contract owner or authorized deployers | ||
*/ | ||
function deployContracts(uint32 chainSlug) external async { | ||
// TODO: Add logic to process if token is already deployed on a chain | ||
_deploy(superToken, chainSlug); | ||
} | ||
|
||
/** | ||
* @notice Initialization function for post-deployment setup | ||
* @param chainSlug The unique identifier of the blockchain | ||
* @dev Overrides the initialize function from AppDeployerBase | ||
* @notice This function is automatically called after all contracts are deployed | ||
* @dev Currently implemented as a no-op, can be extended for additional initialization logic | ||
* @custom:note Automatically triggered via AppDeployerBase.allPayloadsExecuted or AppGateway.queueAndDeploy | ||
*/ | ||
function initialize(uint32 chainSlug) public override async {} | ||
} |
Oops, something went wrong.