Skip to content
This repository was archived by the owner on Apr 15, 2025. It is now read-only.

Commit a34d005

Browse files
authored
Merge pull request #8 from NilFoundation/release-2024-10-15
update contracts to 2024.10.15 release
2 parents 285e121 + 9721622 commit a34d005

File tree

2 files changed

+135
-63
lines changed

2 files changed

+135
-63
lines changed

Nil.sol

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,22 @@
11
// SPDX-License-Identifier: MIT
22
pragma solidity ^0.8.0;
33

4+
// CurrencyId is a type that represents a unique currency identifier.
5+
type CurrencyId is address;
6+
7+
using {
8+
currencyIdEqual as ==,
9+
currencyIdNotEqual as !=
10+
} for CurrencyId global;
11+
12+
function currencyIdEqual(CurrencyId a, CurrencyId b) pure returns (bool) {
13+
return CurrencyId.unwrap(a) == CurrencyId.unwrap(b);
14+
}
15+
16+
function currencyIdNotEqual(CurrencyId a, CurrencyId b) pure returns (bool) {
17+
return CurrencyId.unwrap(a) != CurrencyId.unwrap(b);
18+
}
19+
420
library Nil {
521
uint private constant SEND_MESSAGE = 0xfc;
622
address private constant ASYNC_CALL = address(0xfd);
@@ -15,6 +31,7 @@ library Nil {
1531
address private constant AWAIT_CALL = address(0xd6);
1632
address private constant CONFIG_PARAM = address(0xd7);
1733
address private constant SEND_REQUEST = address(0xd8);
34+
address public constant IS_RESPONSE_MESSAGE = address(0xd9);
1835

1936
// The following constants specify from where and how the gas should be taken during async call.
2037
// Forwarding values are calculated in the following order: FORWARD_VALUE, FORWARD_PERCENTAGE, FORWARD_REMAINING.
@@ -33,7 +50,7 @@ library Nil {
3350

3451
// Token is a struct that represents a token with an id and amount.
3552
struct Token {
36-
uint256 id;
53+
CurrencyId id;
3754
uint256 amount;
3855
}
3956

@@ -167,7 +184,7 @@ library Nil {
167184
}
168185

169186
// getCurrencyBalance returns the balance of a token with a given id for a given address.
170-
function currencyBalance(address addr, uint256 id) internal view returns(uint256) {
187+
function currencyBalance(address addr, CurrencyId id) internal view returns(uint256) {
171188
return __Precompile__(GET_CURRENCY_BALANCE).precompileGetCurrencyBalance(id, addr);
172189
}
173190

@@ -255,13 +272,26 @@ library Nil {
255272

256273
// NilBase is a base contract that provides modifiers for checking the type of message (internal or external).
257274
contract NilBase {
258-
// onlyInternal checks that method was invoked from internal message.
275+
/**
276+
* @dev Modifier to check that the method was invoked from a response message.
277+
*/
278+
modifier onlyResponse() {
279+
(bool success,/* bytes memory returnData*/) = Nil.IS_RESPONSE_MESSAGE.staticcall(bytes(""));
280+
require(success, "IS_RESPONSE_MESSAGE call failed");
281+
_;
282+
}
283+
284+
/**
285+
* @dev Modifier to check that the method was invoked from an internal message.
286+
*/
259287
modifier onlyInternal() {
260288
require(isInternalMessage(), "Trying to call internal function with external message");
261289
_;
262290
}
263291

264-
// onlyExternal checks that method was invoked from external message.
292+
/**
293+
* @dev Modifier to check that the method was invoked from an external message.
294+
*/
265295
modifier onlyExternal() {
266296
require(!isInternalMessage(), "Trying to call external function with internal message");
267297
_;
@@ -285,7 +315,7 @@ abstract contract NilBounceable is NilBase {
285315
contract __Precompile__ {
286316
// if mint flag is set to false, currency will be burned instead
287317
function precompileManageCurrency(uint256 amount, bool mint) public returns(bool) {}
288-
function precompileGetCurrencyBalance(uint256 id, address addr) public view returns(uint256) {}
318+
function precompileGetCurrencyBalance(CurrencyId id, address addr) public view returns(uint256) {}
289319
function precompileAsyncCall(bool, uint8, address, address, address, uint, Nil.Token[] memory, bytes memory) public payable returns(bool) {}
290320
function precompileAwaitCall(address, uint, bytes memory) public payable returns(bytes memory, bool) {}
291321
function precompileSendRequest(address, Nil.Token[] memory, uint, bytes memory, bytes memory) public payable returns(bool) {}
@@ -299,4 +329,5 @@ contract __Precompile__ {
299329
contract NilConfigAbi {
300330
function curr_validators(Nil.ParamValidators memory) public {}
301331
function gas_price(Nil.ParamGasPrice memory) public {}
302-
}
332+
}
333+

NilCurrencyBase.sol

Lines changed: 98 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,88 +1,129 @@
1-
// SPDX-License-Identifier: GPL-3.0
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity ^0.8.0;
23

3-
pragma solidity ^0.8.9;
4-
5-
import "./NilCurrencyBase.sol";
4+
import "./Nil.sol";
65

76
/**
8-
* @title Wallet
9-
* @dev Basic Wallet contract which provides functional for calling another contracts and sending tokens.
10-
* It also supports multi-currency functionality providing methods for minting and sending currency.
11-
* NilCurrencyBase class implements functional for managing own currency(where `currencyId = address(this)`).
7+
* @title NilCurrencyBase
8+
* @dev Abstract contract that provides functionality for currency processing.
9+
* Methods with "Internal" suffix are internal, which means that they can be called only from the derived contract
10+
* itself. But there are default wrapper methods that provide the account owner access to internal methods.
11+
* They are virtual, so the main contract can disable them by overriding them. Then only logic of the contract can use
12+
* internal methods.
1213
*/
13-
contract Wallet is NilCurrencyBase {
14+
abstract contract NilCurrencyBase is NilBase {
15+
uint totalSupply;
16+
string tokenName;
17+
18+
/**
19+
* @dev Returns the total supply of the currency.
20+
* @return The total supply of the currency.
21+
*/
22+
function getCurrencyTotalSupply() public view returns(uint) {
23+
return totalSupply;
24+
}
1425

15-
bytes pubkey;
26+
/**
27+
* @dev Returns the balance of the currency owned by this contract.
28+
* @return The balance of the currency owned by this contract.
29+
*/
30+
function getOwnCurrencyBalance() public view returns(uint256) {
31+
return Nil.currencyBalance(address(this), getCurrencyId());
32+
}
1633

1734
/**
18-
* @dev Fallback function to receive Ether.
35+
* @dev Returns the unique identifier of the currency owned by this contract.
36+
* @return The unique identifier of the currency owned by this contract.
1937
*/
20-
receive() external payable {}
38+
function getCurrencyId() public view returns(CurrencyId) {
39+
return CurrencyId.wrap(address(this));
40+
}
2141

2242
/**
23-
* @dev Function to handle bounce messages.
24-
* @param err The error message.
43+
* @dev Returns the name of the currency.
44+
* @return The name of the currency.
2545
*/
26-
function bounce(string calldata err) external payable {}
46+
function getCurrencyName() public view returns(string memory) {
47+
return tokenName;
48+
}
2749

2850
/**
29-
* @dev Constructor to initialize the wallet with a public key.
30-
* @param _pubkey The public key to initialize the wallet with.
51+
* @dev Set the name of the currency.
52+
* @param name The name of the currency.
3153
*/
32-
constructor(bytes memory _pubkey) payable {
33-
pubkey = _pubkey;
54+
function setCurrencyName(string memory name) onlyExternal virtual public {
55+
tokenName = name;
3456
}
3557

3658
/**
37-
* @dev Sends raw message.
38-
* @param message The raw message to send.
59+
* @dev Mints a specified amount of currency using external call.
60+
* It is wrapper over `mintCurrencyInternal` method to provide access to the owner of the account.
61+
* @param amount The amount of currency to mint.
3962
*/
40-
function send(bytes calldata message) onlyExternal public {
41-
Nil.sendMessage(message);
63+
function mintCurrency(uint256 amount) onlyExternal virtual public {
64+
mintCurrencyInternal(amount);
4265
}
4366

4467
/**
45-
* @dev Makes an asynchronous call.
46-
* @param dst The destination address.
47-
* @param refundTo The address where to send refund message.
48-
* @param bounceTo The address where to send bounce message.
49-
* @param feeCredit The amount of tokens available to pay all fees during message processing.
50-
* @param deploy Whether to deploy the contract.
51-
* @param tokens The multi-currency tokens to send.
52-
* @param value The value to send.
53-
* @param callData The call data of the called method.
68+
* @dev Burns a specified amount of currency using external call.
69+
* It is wrapper over `burnCurrencyInternal` method to provide access to the owner of the account.
70+
* @param amount The amount of currency to burn.
5471
*/
55-
function asyncCall(
56-
address dst,
57-
address refundTo,
58-
address bounceTo,
59-
uint feeCredit,
60-
bool deploy,
61-
Nil.Token[] memory tokens,
62-
uint value,
63-
bytes calldata callData) onlyExternal public {
64-
Nil.asyncCallWithTokens(dst, refundTo, bounceTo, feeCredit, Nil.FORWARD_NONE, deploy, value, tokens, callData);
72+
function burnCurrency(uint256 amount) onlyExternal virtual public {
73+
burnCurrencyInternal(amount);
6574
}
6675

6776
/**
68-
* @dev Makes a synchronous call, which is just a regular EVM call, without using messages.
69-
* @param dst The destination address.
70-
* @param feeCredit The amount of tokens available to pay all fees during message processing.
71-
* @param value The value to send.
72-
* @param call_data The call data of the called method.
77+
* @dev Sends a specified amount of arbitrary currency to a given address.
78+
* It is wrapper over `sendCurrencyInternal` method to provide access to the owner of the account.
79+
* @param amount The amount of currency to mint.
7380
*/
74-
function syncCall(address dst, uint feeCredit, uint value, bytes memory call_data) onlyExternal public {
75-
(bool success,) = dst.call{value: value, gas: feeCredit}(call_data);
76-
require(success, "Call failed");
81+
function sendCurrency(address to, CurrencyId currencyId, uint256 amount) onlyExternal virtual public {
82+
sendCurrencyInternal(to, currencyId, amount);
7783
}
7884

7985
/**
80-
* @dev Verifies an external message.
81-
* @param hash The hash of the data.
82-
* @param signature The signature to verify.
83-
* @return True if the signature is valid, false otherwise.
86+
* @dev Mints a specified amount of currency and increases the total supply.
87+
* All minting should be carried out using this method.
88+
* @param amount The amount of currency to mint.
8489
*/
85-
function verifyExternal(uint256 hash, bytes calldata signature) external view returns (bool) {
86-
return Nil.validateSignature(pubkey, hash, signature);
90+
function mintCurrencyInternal(uint256 amount) internal {
91+
bool success = __Precompile__(Nil.MANAGE_CURRENCY).precompileManageCurrency(amount, true);
92+
require(success, "Mint failed");
93+
totalSupply += amount;
8794
}
88-
}
95+
96+
/**
97+
* @dev Burns a specified amount of currency and decreases the total supply.
98+
* All burning should be carried out using this method.
99+
* @param amount The amount of currency to mint.
100+
*/
101+
function burnCurrencyInternal(uint256 amount) internal {
102+
require(totalSupply >= amount, "Burn failed: not enough tokens");
103+
bool success = __Precompile__(Nil.MANAGE_CURRENCY).precompileManageCurrency(amount, false);
104+
require(success, "Burn failed");
105+
totalSupply -= amount;
106+
}
107+
108+
/**
109+
* @dev Sends a specified amount of arbitrary currency to a given address.
110+
* @param to The address to send the currency to.
111+
* @param currencyId ID of the currency to send.
112+
* @param amount The amount of currency to send.
113+
*/
114+
function sendCurrencyInternal(address to, CurrencyId currencyId, uint256 amount) internal {
115+
Nil.Token[] memory tokens_ = new Nil.Token[](1);
116+
tokens_[0] = Nil.Token(currencyId, amount);
117+
Nil.asyncCallWithTokens(to, address(0), address(0), 0, Nil.FORWARD_REMAINING, false, 0, tokens_, "");
118+
}
119+
120+
/**
121+
* @dev Returns the balance of the currency for a given address.
122+
* @param account The address to check the balance for.
123+
* @return The balance of the currency for the given address.
124+
*/
125+
function getCurrencyBalanceOf(address account) public view returns(uint256) {
126+
return Nil.currencyBalance(account, getCurrencyId());
127+
}
128+
}
129+

0 commit comments

Comments
 (0)