Skip to content

Commit

Permalink
feat: Get Call Data functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
IaroslavMazur committed Aug 23, 2024
1 parent c02dd5c commit a6598cb
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 5 deletions.
4 changes: 1 addition & 3 deletions src/precompiles/native-tokens/INativeTokens.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@ pragma solidity >=0.8.12;
interface INativeTokens {
function balanceOf(address account, uint256 tokenID) external returns (uint256);
function burn(uint256 subID, address holder, uint256 amount) external;

// TODO: implement `callvalues()`

function getCallValues() external returns (uint256[] memory, uint256[] memory);
function mint(uint256 subID, address recipient, uint256 amount) external;
function transfer(address to, uint256 tokenID, uint256 amount) external;
function transferAndCall(
Expand Down
25 changes: 25 additions & 0 deletions src/precompiles/native-tokens/NativeTokens.sol
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,31 @@ library NativeTokens {
return abi.decode(returnData, (uint256));
}

/// @notice Returns the token ids and amounts of the Native Tokens transferred in the context
/// of the current contract call.
///
/// Requirements:
/// - The caller of this function must be a contract.
///
/// @return tokenIDs The IDs of the transferred Native Tokens.
/// @return amounts The amounts of the transferred Native Tokens.
function getCallValues(address notUsed) internal returns (uint256[] memory, uint256[] memory) {
notUsed;
// ABI encode the input parameters.
bytes memory callData = abi.encodeCall(INativeTokens.getCallValues, ());

// Call the precompile.
(bool success, bytes memory returnData) = PRECOMPILE_NATIVE_TOKENS.delegatecall(callData);

// This is an unexpected error since the VM should have panicked if the call failed.
if (!success) {
revert StdLib_UnknownError("NativeTokens: getCallValues failed");
}

// Decode the return data.
return abi.decode(returnData, (uint256[], uint256[]));
}

/*//////////////////////////////////////////////////////////////////////////
USER-FACING NON-CONSTANT FUNCTIONS
//////////////////////////////////////////////////////////////////////////*/
Expand Down
30 changes: 28 additions & 2 deletions src/standards/srf-20/ContractToTransferAndCallTo.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@ contract ContractToTransferAndCallTo {

function transferTokenForAFee(address recipient, uint256 tokenID, uint256 amount, uint256 fee) external payable {
require(fee < amount, "Fee must be less than the amount to transfer");
// TODO: check that the caller has transferred amount worth of the tokenID token

// Make sure the caller has transferred enough tokenID tokens
(uint256[] memory tokenIds, uint256[] memory tokenAmounts) = address(this).getCallValues();
require(tokenIds.length == 1 && tokenAmounts.length == 1, "Caller must have transferred exactly one token");
require(tokenIds[0] == tokenID && tokenAmounts[0] == amount, "Caller must transfer the token to the callee");

// Transfer the token to the provided recipient.
recipient.transfer(tokenID, amount - fee);
Expand All @@ -29,10 +33,32 @@ contract ContractToTransferAndCallTo {

for (uint256 i = 0; i < tokenIDs.length; i++) {
require(fee < amounts[i], "Fee must be less than the amount to transfer");
// TODO: check that the caller has transferred amounts[i] worth of the tokenIDs[i] token

// Make sure the caller has transferred amounts[i] worth of the tokenIDs[i] token
require(
enoughTokensTransferred(tokenIDs[i], amounts[i], tokenIDs, amounts), "Not enough tokens transferred"
);

// Transfer the token to the provided recipient.
recipient.transfer(tokenIDs[i], amounts[i] - fee);
}
}

function enoughTokensTransferred(
uint256 tokenId,
uint256 tokenAmount,
uint256[] memory tokenIds,
uint256[] memory tokenAmounts
)
internal
pure
returns (bool)
{
for (uint256 i = 0; i < tokenIds.length; i++) {
if (tokenIds[i] == tokenId && tokenAmounts[i] == tokenAmount) {
return true;
}
}
return false;
}
}
6 changes: 6 additions & 0 deletions src/standards/srf-20/NaiveTokenTransferrerMock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ contract NaiveTokenTransferrerMock {
return account.balanceOf(tokenID);
}

function getCallValues() external payable returns (uint256[] memory, uint256[] memory) {
// TODO: make the getCallValues() function callable directly from the Precompile, w/o having to call it on an
// address?
return address(this).getCallValues();
}

function transfer(address to, uint256 tokenID, uint256 amount) external {
to.transfer(tokenID, amount);
}
Expand Down

0 comments on commit a6598cb

Please sign in to comment.