Skip to content

Commit

Permalink
update contracts to 2024.10.01 release
Browse files Browse the repository at this point in the history
  • Loading branch information
Gezort authored Oct 1, 2024
1 parent ab5c206 commit 285e121
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 111 deletions.
78 changes: 42 additions & 36 deletions Nil.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ library Nil {
address private constant ASYNC_CALL = address(0xfd);
address public constant VERIFY_SIGNATURE = address(0xfe);
address public constant IS_INTERNAL_MESSAGE = address(0xff);
address public constant MINT_CURRENCY = address(0xd0);
address public constant MANAGE_CURRENCY = address(0xd0);
address private constant GET_CURRENCY_BALANCE = address(0xd1);
address private constant SEND_CURRENCY_SYNC = address(0xd2);
address private constant GET_MESSAGE_TOKENS = address(0xd3);
Expand All @@ -28,6 +28,8 @@ library Nil {
uint8 public constant FORWARD_VALUE = 2;
// Do not forward gas from inbound message, take gas from the account instead.
uint8 public constant FORWARD_NONE = 3;
// Minimal amount of gas reserved by AWAIT_CALL / SEND_REQUEST
uint public constant ASYNC_REQUEST_MIN_GAS = 50_000;

// Token is a struct that represents a token with an id and amount.
struct Token {
Expand All @@ -43,16 +45,7 @@ library Nil {
uint value,
bytes memory callData
) internal {
Token[] memory tokens;
asyncCall(dst, address(0), bounceTo, 0, FORWARD_REMAINING, false, value, tokens, callData);
}

// awaitCall makes an asynchronous call to `dst` contract and waits for the result.
function awaitCall(
address dst,
bytes memory callData
) internal returns(bytes memory, bool) {
return __Precompile__(AWAIT_CALL).precompileAwaitCall(dst, callData);
asyncCall(dst, address(0), bounceTo, 0, FORWARD_REMAINING, false, value, callData);
}

// asyncCall makes an asynchronous call to `dst` contract.
Expand All @@ -67,11 +60,11 @@ library Nil {
bytes memory callData
) internal {
Token[] memory tokens;
asyncCall(dst, refundTo, bounceTo, feeCredit, forwardKind, deploy, value, tokens, callData);
asyncCallWithTokens(dst, refundTo, bounceTo, feeCredit, forwardKind, deploy, value, tokens, callData);
}

// asyncCall makes an asynchronous call to `dst` contract.
function asyncCall(
// asyncCallWithTokens makes an asynchronous call to `dst` contract with native currency tokens attached
function asyncCallWithTokens(
address dst,
address refundTo,
address bounceTo,
Expand All @@ -86,21 +79,6 @@ library Nil {
bounceTo, feeCredit, tokens, callData);
}

// asyncCall makes an asynchronous call to `dst` contract.
function asyncCall(
address dst,
address refundTo,
address bounceTo,
uint feeCredit,
bool deploy,
uint value,
Token[] memory tokens,
bytes memory callData
) internal {
__Precompile__(ASYNC_CALL).precompileAsyncCall{value: value}(deploy, FORWARD_NONE, dst, refundTo,
bounceTo, feeCredit, tokens, callData);
}

function syncCall(
address dst,
uint gas,
Expand All @@ -115,22 +93,49 @@ library Nil {
return (success, returnData);
}

// awaitCall makes an asynchronous call to `dst` contract and waits for the result.
//
// `responseProcessingGas` amount of gas is being bought and reserved to process the response
// should be >= `ASYNC_REQUEST_MIN_GAS` to make a call, otherwise `sendRequest` will fail
function awaitCall(
address dst,
uint responseProcessingGas,
bytes memory callData
) internal returns(bytes memory, bool) {
return __Precompile__(AWAIT_CALL).precompileAwaitCall(dst, responseProcessingGas, callData);
}

// `responseProcessingGas` amount of gas is being bought and reserved to process the response
// should be >= `ASYNC_REQUEST_MIN_GAS` to make a call, otherwise `sendRequest` will fail
function sendRequest(
address dst,
uint256 value,
uint responseProcessingGas,
bytes memory context,
bytes memory callData
) internal {
__Precompile__(SEND_REQUEST).precompileSendRequest{value: value}(dst, context, callData);
Token[] memory tokens;
__Precompile__(SEND_REQUEST).precompileSendRequest{value: value}(dst, tokens, responseProcessingGas, context, callData);
}

function sendRequestWithTokens(
address dst,
uint256 value,
Token[] memory tokens,
uint responseProcessingGas,
bytes memory context,
bytes memory callData
) internal {
__Precompile__(SEND_REQUEST).precompileSendRequest{value: value}(dst, tokens, responseProcessingGas, context, callData);
}

// Send raw internal message using a special precompiled contract
function sendMessage(uint g, bytes memory message) internal {
function sendMessage(bytes memory message) internal {
uint message_size = message.length;
assembly {
// Call precompiled contract.
// Arguments: gas, precompiled address, value, input, input size, output, output size
if iszero(call(g, SEND_MESSAGE, 0, add(message, 32), message_size, 0, 0)) {
if iszero(call(gas(), SEND_MESSAGE, 0, add(message, 32), message_size, 0, 0)) {
revert(0, 0)
}
}
Expand Down Expand Up @@ -278,11 +283,12 @@ abstract contract NilBounceable is NilBase {

// WARNING: User should never use this contract directly.
contract __Precompile__ {
function precompileMintCurrency(uint256 amount) public returns(bool) {}
// if mint flag is set to false, currency will be burned instead
function precompileManageCurrency(uint256 amount, bool mint) public returns(bool) {}
function precompileGetCurrencyBalance(uint256 id, address addr) public view returns(uint256) {}
function precompileAsyncCall(bool, uint8, address, address, address, uint, Nil.Token[] memory, bytes memory) public payable returns(bool) {}
function precompileAwaitCall(address, bytes memory) public payable returns(bytes memory, bool) {}
function precompileSendRequest(address, bytes memory, bytes memory) public payable returns(bool) {}
function precompileAwaitCall(address, uint, bytes memory) public payable returns(bytes memory, bool) {}
function precompileSendRequest(address, Nil.Token[] memory, uint, bytes memory, bytes memory) public payable returns(bool) {}
function precompileSendTokens(address, Nil.Token[] memory) public returns(bool) {}
function precompileGetMessageTokens() public returns(Nil.Token[] memory) {}
function precompileGetGasPrice(uint id) public returns(uint256) {}
Expand All @@ -293,4 +299,4 @@ contract __Precompile__ {
contract NilConfigAbi {
function curr_validators(Nil.ParamValidators memory) public {}
function gas_price(Nil.ParamGasPrice memory) public {}
}
}
131 changes: 56 additions & 75 deletions NilCurrencyBase.sol
Original file line number Diff line number Diff line change
@@ -1,107 +1,88 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
// SPDX-License-Identifier: GPL-3.0

import "./Nil.sol";
pragma solidity ^0.8.9;

import "./NilCurrencyBase.sol";

/**
* @title NilCurrencyBase
* @dev Abstract contract that provides functionality for currency processing.
* Methods with "Internal" suffix are internal, which means that they can be called only from the derived contract
* itself. But there are default wrapper methods that provide the account owner access to internal methods.
* They are virtual, so the main contract can disable them by overriding them. Then only logic of the contract can use
* internal methods.
* @title Wallet
* @dev Basic Wallet contract which provides functional for calling another contracts and sending tokens.
* It also supports multi-currency functionality providing methods for minting and sending currency.
* NilCurrencyBase class implements functional for managing own currency(where `currencyId = address(this)`).
*/
abstract contract NilCurrencyBase is NilBase {
uint totalSupply;
string tokenName;

/**
* @dev Returns the total supply of the currency.
* @return The total supply of the currency.
*/
function getCurrencyTotalSupply() public view returns(uint) {
return totalSupply;
}

/**
* @dev Returns the balance of the currency owned by this contract.
* @return The balance of the currency owned by this contract.
*/
function getOwnCurrencyBalance() public view returns(uint256) {
return Nil.currencyBalance(address(this), getCurrencyId());
}
contract Wallet is NilCurrencyBase {

/**
* @dev Returns the unique identifier of the currency owned by this contract.
* @return The unique identifier of the currency owned by this contract.
*/
function getCurrencyId() public view returns(uint256) {
return uint256(uint160(address(this)));
}
bytes pubkey;

/**
* @dev Returns the name of the currency.
* @return The name of the currency.
* @dev Fallback function to receive Ether.
*/
function getCurrencyName() public view returns(string memory) {
return tokenName;
}
receive() external payable {}

/**
* @dev Set the name of the currency.
* @param name The name of the currency.
* @dev Function to handle bounce messages.
* @param err The error message.
*/
function setCurrencyName(string memory name) onlyExternal virtual public {
tokenName = name;
}
function bounce(string calldata err) external payable {}

/**
* @dev Mints a specified amount of currency using external call.
* It is wrapper over `mintCurrencyInternal` method to provide access to the owner of the account.
* @param amount The amount of currency to mint.
* @dev Constructor to initialize the wallet with a public key.
* @param _pubkey The public key to initialize the wallet with.
*/
function mintCurrency(uint256 amount) onlyExternal virtual public {
mintCurrencyInternal(amount);
constructor(bytes memory _pubkey) payable {
pubkey = _pubkey;
}

/**
* @dev Sends a specified amount of arbitrary currency to a given address.
* It is wrapper over `sendCurrencyInternal` method to provide access to the owner of the account.
* @param amount The amount of currency to mint.
* @dev Sends raw message.
* @param message The raw message to send.
*/
function sendCurrency(address to, uint256 currencyId, uint256 amount) onlyExternal virtual public {
sendCurrencyInternal(to, currencyId, amount);
function send(bytes calldata message) onlyExternal public {
Nil.sendMessage(message);
}

/**
* @dev Mints a specified amount of currency and increases the total supply.
* All minting should be carried out using this method.
* @param amount The amount of currency to mint.
* @dev Makes an asynchronous call.
* @param dst The destination address.
* @param refundTo The address where to send refund message.
* @param bounceTo The address where to send bounce message.
* @param feeCredit The amount of tokens available to pay all fees during message processing.
* @param deploy Whether to deploy the contract.
* @param tokens The multi-currency tokens to send.
* @param value The value to send.
* @param callData The call data of the called method.
*/
function mintCurrencyInternal(uint256 amount) internal {
bool success = __Precompile__(Nil.MINT_CURRENCY).precompileMintCurrency(amount);
require(success, "Mint failed");
totalSupply += amount;
function asyncCall(
address dst,
address refundTo,
address bounceTo,
uint feeCredit,
bool deploy,
Nil.Token[] memory tokens,
uint value,
bytes calldata callData) onlyExternal public {
Nil.asyncCallWithTokens(dst, refundTo, bounceTo, feeCredit, Nil.FORWARD_NONE, deploy, value, tokens, callData);
}

/**
* @dev Sends a specified amount of arbitrary currency to a given address.
* @param to The address to send the currency to.
* @param currencyId ID of the currency to send.
* @param amount The amount of currency to send.
* @dev Makes a synchronous call, which is just a regular EVM call, without using messages.
* @param dst The destination address.
* @param feeCredit The amount of tokens available to pay all fees during message processing.
* @param value The value to send.
* @param call_data The call data of the called method.
*/
function sendCurrencyInternal(address to, uint256 currencyId, uint256 amount) internal {
Nil.Token[] memory tokens_ = new Nil.Token[](1);
tokens_[0] = Nil.Token(currencyId, amount);
Nil.asyncCall(to, address(0), address(0), 0, Nil.FORWARD_REMAINING, false, 0, tokens_, "");
function syncCall(address dst, uint feeCredit, uint value, bytes memory call_data) onlyExternal public {
(bool success,) = dst.call{value: value, gas: feeCredit}(call_data);
require(success, "Call failed");
}

/**
* @dev Returns the balance of the currency for a given address.
* @param account The address to check the balance for.
* @return The balance of the currency for the given address.
* @dev Verifies an external message.
* @param hash The hash of the data.
* @param signature The signature to verify.
* @return True if the signature is valid, false otherwise.
*/
function getCurrencyBalanceOf(address account) public view returns(uint256) {
return Nil.currencyBalance(account, getCurrencyId());
function verifyExternal(uint256 hash, bytes calldata signature) external view returns (bool) {
return Nil.validateSignature(pubkey, hash, signature);
}
}

0 comments on commit 285e121

Please sign in to comment.