mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
fix: corrects _ prefixes
This commit is contained in:
parent
7f360e61fc
commit
beb51068bb
@ -45,10 +45,10 @@ Solidity language without a compiler change.
|
|||||||
pragma solidity >=0.4.16 <0.9.0;
|
pragma solidity >=0.4.16 <0.9.0;
|
||||||
|
|
||||||
library GetCode {
|
library GetCode {
|
||||||
function at(address _addr) public view returns (bytes memory code) {
|
function at(address addr) public view returns (bytes memory code) {
|
||||||
assembly {
|
assembly {
|
||||||
// retrieve the size of the code, this needs assembly
|
// retrieve the size of the code, this needs assembly
|
||||||
let size := extcodesize(_addr)
|
let size := extcodesize(addr)
|
||||||
// allocate output byte array - this could also be done without assembly
|
// allocate output byte array - this could also be done without assembly
|
||||||
// by using code = new bytes(size)
|
// by using code = new bytes(size)
|
||||||
code := mload(0x40)
|
code := mload(0x40)
|
||||||
@ -57,7 +57,7 @@ Solidity language without a compiler change.
|
|||||||
// store length in memory
|
// store length in memory
|
||||||
mstore(code, size)
|
mstore(code, size)
|
||||||
// actually retrieve the code, this needs assembly
|
// actually retrieve the code, this needs assembly
|
||||||
extcodecopy(_addr, add(code, 0x20), 0, size)
|
extcodecopy(addr, add(code, 0x20), 0, size)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -74,43 +74,43 @@ efficient code, for example:
|
|||||||
library VectorSum {
|
library VectorSum {
|
||||||
// This function is less efficient because the optimizer currently fails to
|
// This function is less efficient because the optimizer currently fails to
|
||||||
// remove the bounds checks in array access.
|
// remove the bounds checks in array access.
|
||||||
function sumSolidity(uint[] memory _data) public pure returns (uint sum) {
|
function sumSolidity(uint[] memory data) public pure returns (uint sum) {
|
||||||
for (uint i = 0; i < _data.length; ++i)
|
for (uint i = 0; i < data.length; ++i)
|
||||||
sum += _data[i];
|
sum += data[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
// We know that we only access the array in bounds, so we can avoid the check.
|
// We know that we only access the array in bounds, so we can avoid the check.
|
||||||
// 0x20 needs to be added to an array because the first slot contains the
|
// 0x20 needs to be added to an array because the first slot contains the
|
||||||
// array length.
|
// array length.
|
||||||
function sumAsm(uint[] memory _data) public pure returns (uint sum) {
|
function sumAsm(uint[] memory data) public pure returns (uint sum) {
|
||||||
for (uint i = 0; i < _data.length; ++i) {
|
for (uint i = 0; i < data.length; ++i) {
|
||||||
assembly {
|
assembly {
|
||||||
sum := add(sum, mload(add(add(_data, 0x20), mul(i, 0x20))))
|
sum := add(sum, mload(add(add(data, 0x20), mul(i, 0x20))))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Same as above, but accomplish the entire code within inline assembly.
|
// Same as above, but accomplish the entire code within inline assembly.
|
||||||
function sumPureAsm(uint[] memory _data) public pure returns (uint sum) {
|
function sumPureAsm(uint[] memory data) public pure returns (uint sum) {
|
||||||
assembly {
|
assembly {
|
||||||
// Load the length (first 32 bytes)
|
// Load the length (first 32 bytes)
|
||||||
let len := mload(_data)
|
let len := mload(data)
|
||||||
|
|
||||||
// Skip over the length field.
|
// Skip over the length field.
|
||||||
//
|
//
|
||||||
// Keep temporary variable so it can be incremented in place.
|
// Keep temporary variable so it can be incremented in place.
|
||||||
//
|
//
|
||||||
// NOTE: incrementing _data would result in an unusable
|
// NOTE: incrementing data would result in an unusable
|
||||||
// _data variable after this assembly block
|
// data variable after this assembly block
|
||||||
let data := add(_data, 0x20)
|
let dataElementLocation := add(data, 0x20)
|
||||||
|
|
||||||
// Iterate until the bound is not met.
|
// Iterate until the bound is not met.
|
||||||
for
|
for
|
||||||
{ let end := add(data, mul(len, 0x20)) }
|
{ let end := add(dataElementLocation, mul(len, 0x20)) }
|
||||||
lt(data, end)
|
lt(dataElementLocation, end)
|
||||||
{ data := add(data, 0x20) }
|
{ data := add(dataElementLocation, 0x20) }
|
||||||
{
|
{
|
||||||
sum := add(sum, mload(data))
|
sum := add(sum, mload(dataElementLocation))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -163,9 +163,9 @@ restrictions highly readable.
|
|||||||
// prepend a check that only passes
|
// prepend a check that only passes
|
||||||
// if the function is called from
|
// if the function is called from
|
||||||
// a certain address.
|
// a certain address.
|
||||||
modifier onlyBy(address _account)
|
modifier onlyBy(address account)
|
||||||
{
|
{
|
||||||
if (msg.sender != _account)
|
if (msg.sender != account)
|
||||||
revert Unauthorized();
|
revert Unauthorized();
|
||||||
// Do not forget the "_;"! It will
|
// Do not forget the "_;"! It will
|
||||||
// be replaced by the actual function
|
// be replaced by the actual function
|
||||||
@ -173,17 +173,17 @@ restrictions highly readable.
|
|||||||
_;
|
_;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Make `_newOwner` the new owner of this
|
/// Make `newOwner` the new owner of this
|
||||||
/// contract.
|
/// contract.
|
||||||
function changeOwner(address _newOwner)
|
function changeOwner(address newOwner)
|
||||||
public
|
public
|
||||||
onlyBy(owner)
|
onlyBy(owner)
|
||||||
{
|
{
|
||||||
owner = _newOwner;
|
owner = newOwner;
|
||||||
}
|
}
|
||||||
|
|
||||||
modifier onlyAfter(uint _time) {
|
modifier onlyAfter(uint time) {
|
||||||
if (block.timestamp < _time)
|
if (block.timestamp < time)
|
||||||
revert TooEarly();
|
revert TooEarly();
|
||||||
_;
|
_;
|
||||||
}
|
}
|
||||||
@ -205,21 +205,21 @@ restrictions highly readable.
|
|||||||
// refunded, but only after the function body.
|
// refunded, but only after the function body.
|
||||||
// This was dangerous before Solidity version 0.4.0,
|
// This was dangerous before Solidity version 0.4.0,
|
||||||
// where it was possible to skip the part after `_;`.
|
// where it was possible to skip the part after `_;`.
|
||||||
modifier costs(uint _amount) {
|
modifier costs(uint amount) {
|
||||||
if (msg.value < _amount)
|
if (msg.value < amount)
|
||||||
revert NotEnoughEther();
|
revert NotEnoughEther();
|
||||||
|
|
||||||
_;
|
_;
|
||||||
if (msg.value > _amount)
|
if (msg.value > amount)
|
||||||
payable(msg.sender).transfer(msg.value - _amount);
|
payable(msg.sender).transfer(msg.value - amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
function forceOwnerChange(address _newOwner)
|
function forceOwnerChange(address newOwner)
|
||||||
public
|
public
|
||||||
payable
|
payable
|
||||||
costs(200 ether)
|
costs(200 ether)
|
||||||
{
|
{
|
||||||
owner = _newOwner;
|
owner = newOwner;
|
||||||
// just some example condition
|
// just some example condition
|
||||||
if (uint160(owner) & 0 == 1)
|
if (uint160(owner) & 0 == 1)
|
||||||
// This did not refund for Solidity
|
// This did not refund for Solidity
|
||||||
@ -315,8 +315,8 @@ function finishes.
|
|||||||
|
|
||||||
uint public creationTime = block.timestamp;
|
uint public creationTime = block.timestamp;
|
||||||
|
|
||||||
modifier atStage(Stages _stage) {
|
modifier atStage(Stages stage_) {
|
||||||
if (stage != _stage)
|
if (stage != stage_)
|
||||||
revert FunctionInvalidAtThisStage();
|
revert FunctionInvalidAtThisStage();
|
||||||
_;
|
_;
|
||||||
}
|
}
|
||||||
|
@ -41,14 +41,14 @@ Not all types for constants and immutables are implemented at this time. The onl
|
|||||||
uint immutable maxBalance;
|
uint immutable maxBalance;
|
||||||
address immutable owner = msg.sender;
|
address immutable owner = msg.sender;
|
||||||
|
|
||||||
constructor(uint _decimals, address _reference) {
|
constructor(uint decimals_, address ref) {
|
||||||
decimals = _decimals;
|
decimals = decimals_;
|
||||||
// Assignments to immutables can even access the environment.
|
// Assignments to immutables can even access the environment.
|
||||||
maxBalance = _reference.balance;
|
maxBalance = ref.balance;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isBalanceTooHigh(address _other) public view returns (bool) {
|
function isBalanceTooHigh(address other) public view returns (bool) {
|
||||||
return _other.balance > maxBalance;
|
return other.balance > maxBalance;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ This means that cyclic creation dependencies are impossible.
|
|||||||
|
|
||||||
// This is the constructor which registers the
|
// This is the constructor which registers the
|
||||||
// creator and the assigned name.
|
// creator and the assigned name.
|
||||||
constructor(bytes32 _name) {
|
constructor(bytes32 name_) {
|
||||||
// State variables are accessed via their name
|
// State variables are accessed via their name
|
||||||
// and not via e.g. `this.owner`. Functions can
|
// and not via e.g. `this.owner`. Functions can
|
||||||
// be accessed directly or through `this.f`,
|
// be accessed directly or through `this.f`,
|
||||||
@ -65,7 +65,7 @@ This means that cyclic creation dependencies are impossible.
|
|||||||
// no real way to verify that.
|
// no real way to verify that.
|
||||||
// This does not create a new contract.
|
// This does not create a new contract.
|
||||||
creator = TokenCreator(msg.sender);
|
creator = TokenCreator(msg.sender);
|
||||||
name = _name;
|
name = name_;
|
||||||
}
|
}
|
||||||
|
|
||||||
function changeName(bytes32 newName) public {
|
function changeName(bytes32 newName) public {
|
||||||
|
@ -80,18 +80,18 @@ four indexed arguments rather than three.
|
|||||||
|
|
||||||
contract ClientReceipt {
|
contract ClientReceipt {
|
||||||
event Deposit(
|
event Deposit(
|
||||||
address indexed _from,
|
address indexed from,
|
||||||
bytes32 indexed _id,
|
bytes32 indexed id,
|
||||||
uint _value
|
uint value
|
||||||
);
|
);
|
||||||
|
|
||||||
function deposit(bytes32 _id) public payable {
|
function deposit(bytes32 id) public payable {
|
||||||
// Events are emitted using `emit`, followed by
|
// Events are emitted using `emit`, followed by
|
||||||
// the name of the event and the arguments
|
// the name of the event and the arguments
|
||||||
// (if any) in parentheses. Any such invocation
|
// (if any) in parentheses. Any such invocation
|
||||||
// (even deeply nested) can be detected from
|
// (even deeply nested) can be detected from
|
||||||
// the JavaScript API by filtering for `Deposit`.
|
// the JavaScript API by filtering for `Deposit`.
|
||||||
emit Deposit(msg.sender, _id, msg.value);
|
emit Deposit(msg.sender, id, msg.value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,9 +126,9 @@ The output of the above looks like the following (trimmed):
|
|||||||
|
|
||||||
{
|
{
|
||||||
"returnValues": {
|
"returnValues": {
|
||||||
"_from": "0x1111…FFFFCCCC",
|
"from": "0x1111…FFFFCCCC",
|
||||||
"_id": "0x50…sd5adb20",
|
"id": "0x50…sd5adb20",
|
||||||
"_value": "0x420042"
|
"value": "0x420042"
|
||||||
},
|
},
|
||||||
"raw": {
|
"raw": {
|
||||||
"data": "0x7f…91385",
|
"data": "0x7f…91385",
|
||||||
|
@ -72,8 +72,8 @@ if they are marked ``virtual``. For details, please see
|
|||||||
registeredAddresses[msg.sender] = true;
|
registeredAddresses[msg.sender] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function changePrice(uint _price) public onlyOwner {
|
function changePrice(uint price_) public onlyOwner {
|
||||||
price = _price;
|
price = price_;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,17 +17,17 @@ that call them, similar to internal library functions.
|
|||||||
// SPDX-License-Identifier: GPL-3.0
|
// SPDX-License-Identifier: GPL-3.0
|
||||||
pragma solidity >=0.7.1 <0.9.0;
|
pragma solidity >=0.7.1 <0.9.0;
|
||||||
|
|
||||||
function sum(uint[] memory _arr) pure returns (uint s) {
|
function sum(uint[] memory arr) pure returns (uint s) {
|
||||||
for (uint i = 0; i < _arr.length; i++)
|
for (uint i = 0; i < arr.length; i++)
|
||||||
s += _arr[i];
|
s += arr[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
contract ArrayExample {
|
contract ArrayExample {
|
||||||
bool found;
|
bool found;
|
||||||
function f(uint[] memory _arr) public {
|
function f(uint[] memory arr) public {
|
||||||
// This calls the free function internally.
|
// This calls the free function internally.
|
||||||
// The compiler will add its code to the contract.
|
// The compiler will add its code to the contract.
|
||||||
uint s = sum(_arr);
|
uint s = sum(arr);
|
||||||
require(s >= 10);
|
require(s >= 10);
|
||||||
found = true;
|
found = true;
|
||||||
}
|
}
|
||||||
@ -65,8 +65,8 @@ with two integers, you would use something like the following:
|
|||||||
|
|
||||||
contract Simple {
|
contract Simple {
|
||||||
uint sum;
|
uint sum;
|
||||||
function taker(uint _a, uint _b) public {
|
function taker(uint a, uint b) public {
|
||||||
sum = _a + _b;
|
sum = a + b;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,13 +99,13 @@ two integers passed as function parameters, then you use something like:
|
|||||||
pragma solidity >=0.4.16 <0.9.0;
|
pragma solidity >=0.4.16 <0.9.0;
|
||||||
|
|
||||||
contract Simple {
|
contract Simple {
|
||||||
function arithmetic(uint _a, uint _b)
|
function arithmetic(uint a, uint b)
|
||||||
public
|
public
|
||||||
pure
|
pure
|
||||||
returns (uint sum, uint product)
|
returns (uint sum, uint product)
|
||||||
{
|
{
|
||||||
sum = _a + _b;
|
sum = a + b;
|
||||||
product = _a * _b;
|
product = a * b;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,12 +126,12 @@ statement:
|
|||||||
pragma solidity >=0.4.16 <0.9.0;
|
pragma solidity >=0.4.16 <0.9.0;
|
||||||
|
|
||||||
contract Simple {
|
contract Simple {
|
||||||
function arithmetic(uint _a, uint _b)
|
function arithmetic(uint a, uint b)
|
||||||
public
|
public
|
||||||
pure
|
pure
|
||||||
returns (uint sum, uint product)
|
returns (uint sum, uint product)
|
||||||
{
|
{
|
||||||
return (_a + _b, _a * _b);
|
return (a + b, a * b);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -362,7 +362,7 @@ Fallback Function
|
|||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
A contract can have at most one ``fallback`` function, declared using either ``fallback () external [payable]``
|
A contract can have at most one ``fallback`` function, declared using either ``fallback () external [payable]``
|
||||||
or ``fallback (bytes calldata _input) external [payable] returns (bytes memory _output)``
|
or ``fallback (bytes calldata input) external [payable] returns (bytes memory output)``
|
||||||
(both without the ``function`` keyword).
|
(both without the ``function`` keyword).
|
||||||
This function must have ``external`` visibility. A fallback function can be virtual, can override
|
This function must have ``external`` visibility. A fallback function can be virtual, can override
|
||||||
and can have modifiers.
|
and can have modifiers.
|
||||||
@ -373,8 +373,8 @@ all and there is no :ref:`receive Ether function <receive-ether-function>`.
|
|||||||
The fallback function always receives data, but in order to also receive Ether
|
The fallback function always receives data, but in order to also receive Ether
|
||||||
it must be marked ``payable``.
|
it must be marked ``payable``.
|
||||||
|
|
||||||
If the version with parameters is used, ``_input`` will contain the full data sent to the contract
|
If the version with parameters is used, ``input`` will contain the full data sent to the contract
|
||||||
(equal to ``msg.data``) and can return data in ``_output``. The returned data will not be
|
(equal to ``msg.data``) and can return data in ``output``. The returned data will not be
|
||||||
ABI-encoded. Instead it will be returned without modifications (not even padding).
|
ABI-encoded. Instead it will be returned without modifications (not even padding).
|
||||||
|
|
||||||
In the worst case, if a payable fallback function is also used in
|
In the worst case, if a payable fallback function is also used in
|
||||||
@ -397,7 +397,7 @@ operations as long as there is enough gas passed on to it.
|
|||||||
for the function selector and then
|
for the function selector and then
|
||||||
you can use ``abi.decode`` together with the array slice syntax to
|
you can use ``abi.decode`` together with the array slice syntax to
|
||||||
decode ABI-encoded data:
|
decode ABI-encoded data:
|
||||||
``(c, d) = abi.decode(_input[4:], (uint256, uint256));``
|
``(c, d) = abi.decode(input[4:], (uint256, uint256));``
|
||||||
Note that this should only be used as a last resort and
|
Note that this should only be used as a last resort and
|
||||||
proper functions should be used instead.
|
proper functions should be used instead.
|
||||||
|
|
||||||
@ -486,13 +486,13 @@ The following example shows overloading of the function
|
|||||||
pragma solidity >=0.4.16 <0.9.0;
|
pragma solidity >=0.4.16 <0.9.0;
|
||||||
|
|
||||||
contract A {
|
contract A {
|
||||||
function f(uint _in) public pure returns (uint out) {
|
function f(uint value) public pure returns (uint out) {
|
||||||
out = _in;
|
out = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
function f(uint _in, bool _really) public pure returns (uint out) {
|
function f(uint value, bool really) public pure returns (uint out) {
|
||||||
if (_really)
|
if (really)
|
||||||
out = _in;
|
out = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -506,12 +506,12 @@ externally visible functions differ by their Solidity types but not by their ext
|
|||||||
|
|
||||||
// This will not compile
|
// This will not compile
|
||||||
contract A {
|
contract A {
|
||||||
function f(B _in) public pure returns (B out) {
|
function f(B value) public pure returns (B out) {
|
||||||
out = _in;
|
out = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
function f(address _in) public pure returns (address out) {
|
function f(address value) public pure returns (address out) {
|
||||||
out = _in;
|
out = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -539,12 +539,12 @@ candidate, resolution fails.
|
|||||||
pragma solidity >=0.4.16 <0.9.0;
|
pragma solidity >=0.4.16 <0.9.0;
|
||||||
|
|
||||||
contract A {
|
contract A {
|
||||||
function f(uint8 _in) public pure returns (uint8 out) {
|
function f(uint8 val) public pure returns (uint8 out) {
|
||||||
out = _in;
|
out = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
function f(uint256 _in) public pure returns (uint256 out) {
|
function f(uint256 val) public pure returns (uint256 out) {
|
||||||
out = _in;
|
out = val;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -421,8 +421,8 @@ equivalent to ``constructor() {}``. For example:
|
|||||||
abstract contract A {
|
abstract contract A {
|
||||||
uint public a;
|
uint public a;
|
||||||
|
|
||||||
constructor(uint _a) {
|
constructor(uint a_) {
|
||||||
a = _a;
|
a = a_;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -459,7 +459,7 @@ derived contracts need to specify all of them. This can be done in two ways:
|
|||||||
|
|
||||||
contract Base {
|
contract Base {
|
||||||
uint x;
|
uint x;
|
||||||
constructor(uint _x) { x = _x; }
|
constructor(uint x_) { x = x_; }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Either directly specify in the inheritance list...
|
// Either directly specify in the inheritance list...
|
||||||
@ -469,12 +469,12 @@ derived contracts need to specify all of them. This can be done in two ways:
|
|||||||
|
|
||||||
// or through a "modifier" of the derived constructor.
|
// or through a "modifier" of the derived constructor.
|
||||||
contract Derived2 is Base {
|
contract Derived2 is Base {
|
||||||
constructor(uint _y) Base(_y * _y) {}
|
constructor(uint y) Base(y * y) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
One way is directly in the inheritance list (``is Base(7)``). The other is in
|
One way is directly in the inheritance list (``is Base(7)``). The other is in
|
||||||
the way a modifier is invoked as part of
|
the way a modifier is invoked as part of
|
||||||
the derived constructor (``Base(_y * _y)``). The first way to
|
the derived constructor (``Base(y * y)``). The first way to
|
||||||
do it is more convenient if the constructor argument is a
|
do it is more convenient if the constructor argument is a
|
||||||
constant and defines the behaviour of the contract or
|
constant and defines the behaviour of the contract or
|
||||||
describes it. The second way has to be used if the
|
describes it. The second way has to be used if the
|
||||||
|
@ -146,16 +146,16 @@ custom types without the overhead of external function calls:
|
|||||||
r.limbs[0] = x;
|
r.limbs[0] = x;
|
||||||
}
|
}
|
||||||
|
|
||||||
function add(bigint memory _a, bigint memory _b) internal pure returns (bigint memory r) {
|
function add(bigint memory a, bigint memory b) internal pure returns (bigint memory r) {
|
||||||
r.limbs = new uint[](max(_a.limbs.length, _b.limbs.length));
|
r.limbs = new uint[](max(a.limbs.length, b.limbs.length));
|
||||||
uint carry = 0;
|
uint carry = 0;
|
||||||
for (uint i = 0; i < r.limbs.length; ++i) {
|
for (uint i = 0; i < r.limbs.length; ++i) {
|
||||||
uint a = limb(_a, i);
|
uint limbA = limb(a, i);
|
||||||
uint b = limb(_b, i);
|
uint limbB = limb(b, i);
|
||||||
unchecked {
|
unchecked {
|
||||||
r.limbs[i] = a + b + carry;
|
r.limbs[i] = limbA + limbB + carry;
|
||||||
|
|
||||||
if (a + b < a || (a + b == type(uint).max && carry > 0))
|
if (limbA + limbB < limbA || (limbA + limbB == type(uint).max && carry > 0))
|
||||||
carry = 1;
|
carry = 1;
|
||||||
else
|
else
|
||||||
carry = 0;
|
carry = 0;
|
||||||
@ -172,8 +172,8 @@ custom types without the overhead of external function calls:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function limb(bigint memory _a, uint _limb) internal pure returns (uint) {
|
function limb(bigint memory a, uint index) internal pure returns (uint) {
|
||||||
return _limb < _a.limbs.length ? _a.limbs[_limb] : 0;
|
return index < a.limbs.length ? a.limbs[index] : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
function max(uint a, uint b) private pure returns (uint) {
|
function max(uint a, uint b) private pure returns (uint) {
|
||||||
|
@ -128,13 +128,13 @@ In this example, we will use a library.
|
|||||||
data.push(value);
|
data.push(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
function replace(uint _old, uint _new) public {
|
function replace(uint from, uint to) public {
|
||||||
// This performs the library function call
|
// This performs the library function call
|
||||||
uint index = data.indexOf(_old);
|
uint index = data.indexOf(from);
|
||||||
if (index == type(uint).max)
|
if (index == type(uint).max)
|
||||||
data.push(_new);
|
data.push(to);
|
||||||
else
|
else
|
||||||
data[index] = _new;
|
data[index] = to;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,8 +168,8 @@ following:
|
|||||||
|
|
||||||
.. code-block:: solidity
|
.. code-block:: solidity
|
||||||
|
|
||||||
function balances(address _account) external view returns (uint) {
|
function balances(address account) external view returns (uint) {
|
||||||
return balances[_account];
|
return balances[account];
|
||||||
}
|
}
|
||||||
|
|
||||||
You can use this function to query the balance of a single account.
|
You can use this function to query the balance of a single account.
|
||||||
|
@ -74,8 +74,8 @@ hiding new and different behavior in existing code.
|
|||||||
// SPDX-License-Identifier: GPL-3.0
|
// SPDX-License-Identifier: GPL-3.0
|
||||||
pragma solidity >=0.7.0;
|
pragma solidity >=0.7.0;
|
||||||
contract C {
|
contract C {
|
||||||
function f(uint _a) public pure mod() returns (uint _r) {
|
function f(uint a) public pure mod() returns (uint r) {
|
||||||
_r = _a++;
|
r = a++;
|
||||||
}
|
}
|
||||||
modifier mod() { _; _; }
|
modifier mod() { _; _; }
|
||||||
}
|
}
|
||||||
@ -166,7 +166,7 @@ This causes differences in some contracts, for example:
|
|||||||
|
|
||||||
contract C {
|
contract C {
|
||||||
bytes x;
|
bytes x;
|
||||||
function f() public returns (uint _r) {
|
function f() public returns (uint r) {
|
||||||
bytes memory m = "tmp";
|
bytes memory m = "tmp";
|
||||||
assembly {
|
assembly {
|
||||||
mstore(m, 8)
|
mstore(m, 8)
|
||||||
@ -174,7 +174,7 @@ This causes differences in some contracts, for example:
|
|||||||
}
|
}
|
||||||
x = m;
|
x = m;
|
||||||
assembly {
|
assembly {
|
||||||
_r := sload(x.slot)
|
r := sload(x.slot)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -197,8 +197,8 @@ This causes differences in some contracts, for example:
|
|||||||
// SPDX-License-Identifier: GPL-3.0
|
// SPDX-License-Identifier: GPL-3.0
|
||||||
pragma solidity >=0.8.1;
|
pragma solidity >=0.8.1;
|
||||||
contract C {
|
contract C {
|
||||||
function preincr_u8(uint8 _a) public pure returns (uint8) {
|
function preincr_u8(uint8 a) public pure returns (uint8) {
|
||||||
return ++_a + _a;
|
return ++a + a;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -218,11 +218,11 @@ This causes differences in some contracts, for example:
|
|||||||
// SPDX-License-Identifier: GPL-3.0
|
// SPDX-License-Identifier: GPL-3.0
|
||||||
pragma solidity >=0.8.1;
|
pragma solidity >=0.8.1;
|
||||||
contract C {
|
contract C {
|
||||||
function add(uint8 _a, uint8 _b) public pure returns (uint8) {
|
function add(uint8 a, uint8 b) public pure returns (uint8) {
|
||||||
return _a + _b;
|
return a + b;
|
||||||
}
|
}
|
||||||
function g(uint8 _a, uint8 _b) public pure returns (uint8) {
|
function g(uint8 a, uint8 b) public pure returns (uint8) {
|
||||||
return add(++_a + ++_b, _a + _b);
|
return add(++a + ++b, a + b);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -321,13 +321,13 @@ For example:
|
|||||||
// SPDX-License-Identifier: GPL-3.0
|
// SPDX-License-Identifier: GPL-3.0
|
||||||
pragma solidity >=0.8.1;
|
pragma solidity >=0.8.1;
|
||||||
contract C {
|
contract C {
|
||||||
function f(uint8 _a) public pure returns (uint _r1, uint _r2)
|
function f(uint8 a) public pure returns (uint r1, uint r2)
|
||||||
{
|
{
|
||||||
_a = ~_a;
|
a = ~a;
|
||||||
assembly {
|
assembly {
|
||||||
_r1 := _a
|
r1 := a
|
||||||
}
|
}
|
||||||
_r2 = _a;
|
r2 = a;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -336,6 +336,6 @@ The function ``f(1)`` returns the following values:
|
|||||||
- Old code generator: (``fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe``, ``00000000000000000000000000000000000000000000000000000000000000fe``)
|
- Old code generator: (``fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe``, ``00000000000000000000000000000000000000000000000000000000000000fe``)
|
||||||
- New code generator: (``00000000000000000000000000000000000000000000000000000000000000fe``, ``00000000000000000000000000000000000000000000000000000000000000fe``)
|
- New code generator: (``00000000000000000000000000000000000000000000000000000000000000fe``, ``00000000000000000000000000000000000000000000000000000000000000fe``)
|
||||||
|
|
||||||
Note that, unlike the new code generator, the old code generator does not perform a cleanup after the bit-not assignment (``_a = ~_a``).
|
Note that, unlike the new code generator, the old code generator does not perform a cleanup after the bit-not assignment (``a = ~a``).
|
||||||
This results in different values being assigned (within the inline assembly block) to return value ``_r1`` between the old and new code generators.
|
This results in different values being assigned (within the inline assembly block) to return value ``r1`` between the old and new code generators.
|
||||||
However, both code generators perform a cleanup before the new value of ``_a`` is assigned to ``_r2``.
|
However, both code generators perform a cleanup before the new value of ``a`` is assigned to ``r2``.
|
||||||
|
@ -210,9 +210,9 @@ using a second proxy:
|
|||||||
contract ProxyWithMoreFunctionality {
|
contract ProxyWithMoreFunctionality {
|
||||||
PermissionlessProxy proxy;
|
PermissionlessProxy proxy;
|
||||||
|
|
||||||
function callOther(address _addr, bytes memory _payload) public
|
function callOther(address addr, bytes memory payload) public
|
||||||
returns (bool, bytes memory) {
|
returns (bool, bytes memory) {
|
||||||
return proxy.callOther(_addr, _payload);
|
return proxy.callOther(addr, payload);
|
||||||
}
|
}
|
||||||
// Other functions and other functionality
|
// Other functions and other functionality
|
||||||
}
|
}
|
||||||
@ -220,9 +220,9 @@ using a second proxy:
|
|||||||
// This is the full contract, it has no other functionality and
|
// This is the full contract, it has no other functionality and
|
||||||
// requires no privileges to work.
|
// requires no privileges to work.
|
||||||
contract PermissionlessProxy {
|
contract PermissionlessProxy {
|
||||||
function callOther(address _addr, bytes memory _payload) public
|
function callOther(address addr, bytes memory payload) public
|
||||||
returns (bool, bytes memory) {
|
returns (bool, bytes memory) {
|
||||||
return _addr.call(_payload);
|
return addr.call(payload);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -331,17 +331,17 @@ field of a ``struct`` that is the base type of a dynamic storage array. The
|
|||||||
contract Map {
|
contract Map {
|
||||||
mapping (uint => uint)[] array;
|
mapping (uint => uint)[] array;
|
||||||
|
|
||||||
function allocate(uint _newMaps) public {
|
function allocate(uint newMaps) public {
|
||||||
for (uint i = 0; i < _newMaps; i++)
|
for (uint i = 0; i < newMaps; i++)
|
||||||
array.push();
|
array.push();
|
||||||
}
|
}
|
||||||
|
|
||||||
function writeMap(uint _map, uint _key, uint _value) public {
|
function writeMap(uint map, uint key, uint value) public {
|
||||||
array[_map][_key] = _value;
|
array[map][key] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
function readMap(uint _map, uint _key) public view returns (uint) {
|
function readMap(uint map, uint key) public view returns (uint) {
|
||||||
return array[_map][_key];
|
return array[map][key];
|
||||||
}
|
}
|
||||||
|
|
||||||
function eraseMaps() public {
|
function eraseMaps() public {
|
||||||
|
@ -82,12 +82,12 @@ Overflow
|
|||||||
uint immutable x;
|
uint immutable x;
|
||||||
uint immutable y;
|
uint immutable y;
|
||||||
|
|
||||||
function add(uint _x, uint _y) internal pure returns (uint) {
|
function add(uint x_, uint y_) internal pure returns (uint) {
|
||||||
return _x + _y;
|
return x_ + y_;
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(uint _x, uint _y) {
|
constructor(uint x_, uint y_) {
|
||||||
(x, y) = (_x, _y);
|
(x, y) = (x_, y_);
|
||||||
}
|
}
|
||||||
|
|
||||||
function stateAdd() public view returns (uint) {
|
function stateAdd() public view returns (uint) {
|
||||||
@ -116,7 +116,7 @@ Here, it reports the following:
|
|||||||
Overflow.add(1, 115792089237316195423570985008687907853269984665640564039457584007913129639935) -- internal call
|
Overflow.add(1, 115792089237316195423570985008687907853269984665640564039457584007913129639935) -- internal call
|
||||||
--> o.sol:9:20:
|
--> o.sol:9:20:
|
||||||
|
|
|
|
||||||
9 | return _x + _y;
|
9 | return x_ + y_;
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
|
|
||||||
If we add ``require`` statements that filter out overflow cases,
|
If we add ``require`` statements that filter out overflow cases,
|
||||||
@ -131,12 +131,12 @@ the SMTChecker proves that no overflow is reachable (by not reporting warnings):
|
|||||||
uint immutable x;
|
uint immutable x;
|
||||||
uint immutable y;
|
uint immutable y;
|
||||||
|
|
||||||
function add(uint _x, uint _y) internal pure returns (uint) {
|
function add(uint x_, uint y_) internal pure returns (uint) {
|
||||||
return _x + _y;
|
return x_ + y_;
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(uint _x, uint _y) {
|
constructor(uint x_, uint y_) {
|
||||||
(x, y) = (_x, _y);
|
(x, y) = (x_, y_);
|
||||||
}
|
}
|
||||||
|
|
||||||
function stateAdd() public view returns (uint) {
|
function stateAdd() public view returns (uint) {
|
||||||
@ -155,7 +155,7 @@ An assertion represents an invariant in your code: a property that must be true
|
|||||||
|
|
||||||
The code below defines a function ``f`` that guarantees no overflow.
|
The code below defines a function ``f`` that guarantees no overflow.
|
||||||
Function ``inv`` defines the specification that ``f`` is monotonically increasing:
|
Function ``inv`` defines the specification that ``f`` is monotonically increasing:
|
||||||
for every possible pair ``(_a, _b)``, if ``_b > _a`` then ``f(_b) > f(_a)``.
|
for every possible pair ``(a, b)``, if ``b > a`` then ``f(b) > f(a)``.
|
||||||
Since ``f`` is indeed monotonically increasing, the SMTChecker proves that our
|
Since ``f`` is indeed monotonically increasing, the SMTChecker proves that our
|
||||||
property is correct. You are encouraged to play with the property and the function
|
property is correct. You are encouraged to play with the property and the function
|
||||||
definition to see what results come out!
|
definition to see what results come out!
|
||||||
@ -166,14 +166,14 @@ definition to see what results come out!
|
|||||||
pragma solidity >=0.8.0;
|
pragma solidity >=0.8.0;
|
||||||
|
|
||||||
contract Monotonic {
|
contract Monotonic {
|
||||||
function f(uint _x) internal pure returns (uint) {
|
function f(uint x) internal pure returns (uint) {
|
||||||
require(_x < type(uint128).max);
|
require(x < type(uint128).max);
|
||||||
return _x * 42;
|
return x * 42;
|
||||||
}
|
}
|
||||||
|
|
||||||
function inv(uint _a, uint _b) public pure {
|
function inv(uint a, uint b) public pure {
|
||||||
require(_b > _a);
|
require(b > a);
|
||||||
assert(f(_b) > f(_a));
|
assert(f(b) > f(a));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -188,14 +188,14 @@ equal every element in the array.
|
|||||||
pragma solidity >=0.8.0;
|
pragma solidity >=0.8.0;
|
||||||
|
|
||||||
contract Max {
|
contract Max {
|
||||||
function max(uint[] memory _a) public pure returns (uint) {
|
function max(uint[] memory a) public pure returns (uint) {
|
||||||
uint m = 0;
|
uint m = 0;
|
||||||
for (uint i = 0; i < _a.length; ++i)
|
for (uint i = 0; i < a.length; ++i)
|
||||||
if (_a[i] > m)
|
if (a[i] > m)
|
||||||
m = _a[i];
|
m = a[i];
|
||||||
|
|
||||||
for (uint i = 0; i < _a.length; ++i)
|
for (uint i = 0; i < a.length; ++i)
|
||||||
assert(m >= _a[i]);
|
assert(m >= a[i]);
|
||||||
|
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
@ -222,15 +222,15 @@ For example, changing the code to
|
|||||||
pragma solidity >=0.8.0;
|
pragma solidity >=0.8.0;
|
||||||
|
|
||||||
contract Max {
|
contract Max {
|
||||||
function max(uint[] memory _a) public pure returns (uint) {
|
function max(uint[] memory a) public pure returns (uint) {
|
||||||
require(_a.length >= 5);
|
require(a.length >= 5);
|
||||||
uint m = 0;
|
uint m = 0;
|
||||||
for (uint i = 0; i < _a.length; ++i)
|
for (uint i = 0; i < a.length; ++i)
|
||||||
if (_a[i] > m)
|
if (a[i] > m)
|
||||||
m = _a[i];
|
m = a[i];
|
||||||
|
|
||||||
for (uint i = 0; i < _a.length; ++i)
|
for (uint i = 0; i < a.length; ++i)
|
||||||
assert(m > _a[i]);
|
assert(m > a[i]);
|
||||||
|
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
@ -243,7 +243,7 @@ gives us:
|
|||||||
Warning: CHC: Assertion violation happens here.
|
Warning: CHC: Assertion violation happens here.
|
||||||
Counterexample:
|
Counterexample:
|
||||||
|
|
||||||
_a = [0, 0, 0, 0, 0]
|
a = [0, 0, 0, 0, 0]
|
||||||
= 0
|
= 0
|
||||||
|
|
||||||
Transaction trace:
|
Transaction trace:
|
||||||
@ -251,7 +251,7 @@ gives us:
|
|||||||
Test.max([0, 0, 0, 0, 0])
|
Test.max([0, 0, 0, 0, 0])
|
||||||
--> max.sol:14:4:
|
--> max.sol:14:4:
|
||||||
|
|
|
|
||||||
14 | assert(m > _a[i]);
|
14 | assert(m > a[i]);
|
||||||
|
|
||||||
|
|
||||||
State Properties
|
State Properties
|
||||||
@ -383,9 +383,9 @@ anything, including reenter the caller contract.
|
|||||||
|
|
||||||
Unknown immutable unknown;
|
Unknown immutable unknown;
|
||||||
|
|
||||||
constructor(Unknown _u) {
|
constructor(Unknown u) {
|
||||||
require(address(_u) != address(0));
|
require(address(u) != address(0));
|
||||||
unknown = _u;
|
unknown = u;
|
||||||
}
|
}
|
||||||
|
|
||||||
modifier mutex {
|
modifier mutex {
|
||||||
@ -395,8 +395,8 @@ anything, including reenter the caller contract.
|
|||||||
lock = false;
|
lock = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function set(uint _x) mutex public {
|
function set(uint x_) mutex public {
|
||||||
x = _x;
|
x = x_;
|
||||||
}
|
}
|
||||||
|
|
||||||
function run() mutex public {
|
function run() mutex public {
|
||||||
@ -754,15 +754,15 @@ not mean loss of proving power.
|
|||||||
{
|
{
|
||||||
function f(
|
function f(
|
||||||
bytes32 hash,
|
bytes32 hash,
|
||||||
uint8 _v1, uint8 _v2,
|
uint8 v1, uint8 v2,
|
||||||
bytes32 _r1, bytes32 _r2,
|
bytes32 r1, bytes32 r2,
|
||||||
bytes32 _s1, bytes32 _s2
|
bytes32 s1, bytes32 s2
|
||||||
) public pure returns (address) {
|
) public pure returns (address) {
|
||||||
address a1 = ecrecover(hash, _v1, _r1, _s1);
|
address a1 = ecrecover(hash, v1, r1, s1);
|
||||||
require(_v1 == _v2);
|
require(v1 == v2);
|
||||||
require(_r1 == _r2);
|
require(r1 == r2);
|
||||||
require(_s1 == _s2);
|
require(s1 == s2);
|
||||||
address a2 = ecrecover(hash, _v2, _r2, _s2);
|
address a2 = ecrecover(hash, v2, r2, s2);
|
||||||
assert(a1 == a2);
|
assert(a1 == a2);
|
||||||
return a1;
|
return a1;
|
||||||
}
|
}
|
||||||
|
@ -4,12 +4,12 @@
|
|||||||
Mapping Types
|
Mapping Types
|
||||||
=============
|
=============
|
||||||
|
|
||||||
Mapping types use the syntax ``mapping(_KeyType => _ValueType)`` and variables
|
Mapping types use the syntax ``mapping(KeyType => ValueType)`` and variables
|
||||||
of mapping type are declared using the syntax ``mapping(_KeyType => _ValueType) _VariableName``.
|
of mapping type are declared using the syntax ``mapping(KeyType => ValueType) VariableName``.
|
||||||
The ``_KeyType`` can be any
|
The ``KeyType`` can be any
|
||||||
built-in value type, ``bytes``, ``string``, or any contract or enum type. Other user-defined
|
built-in value type, ``bytes``, ``string``, or any contract or enum type. Other user-defined
|
||||||
or complex types, such as mappings, structs or array types are not allowed.
|
or complex types, such as mappings, structs or array types are not allowed.
|
||||||
``_ValueType`` can be any type, including mappings, arrays and structs.
|
``ValueType`` can be any type, including mappings, arrays and structs.
|
||||||
|
|
||||||
You can think of mappings as `hash tables <https://en.wikipedia.org/wiki/Hash_table>`_, which are virtually initialised
|
You can think of mappings as `hash tables <https://en.wikipedia.org/wiki/Hash_table>`_, which are virtually initialised
|
||||||
such that every possible key exists and is mapped to a value whose
|
such that every possible key exists and is mapped to a value whose
|
||||||
@ -29,10 +29,10 @@ of contract functions that are publicly visible.
|
|||||||
These restrictions are also true for arrays and structs that contain mappings.
|
These restrictions are also true for arrays and structs that contain mappings.
|
||||||
|
|
||||||
You can mark state variables of mapping type as ``public`` and Solidity creates a
|
You can mark state variables of mapping type as ``public`` and Solidity creates a
|
||||||
:ref:`getter <visibility-and-getters>` for you. The ``_KeyType`` becomes a parameter for the getter.
|
:ref:`getter <visibility-and-getters>` for you. The ``KeyType`` becomes a parameter for the getter.
|
||||||
If ``_ValueType`` is a value type or a struct, the getter returns ``_ValueType``.
|
If ``ValueType`` is a value type or a struct, the getter returns ``ValueType``.
|
||||||
If ``_ValueType`` is an array or a mapping, the getter has one parameter for
|
If ``ValueType`` is an array or a mapping, the getter has one parameter for
|
||||||
each ``_KeyType``, recursively.
|
each ``KeyType``, recursively.
|
||||||
|
|
||||||
In the example below, the ``MappingExample`` contract defines a public ``balances``
|
In the example below, the ``MappingExample`` contract defines a public ``balances``
|
||||||
mapping, with the key type an ``address``, and a value type a ``uint``, mapping
|
mapping, with the key type an ``address``, and a value type a ``uint``, mapping
|
||||||
|
@ -511,21 +511,21 @@ Array slices are useful to ABI-decode secondary data passed in function paramete
|
|||||||
/// @dev Address of the client contract managed by proxy i.e., this contract
|
/// @dev Address of the client contract managed by proxy i.e., this contract
|
||||||
address client;
|
address client;
|
||||||
|
|
||||||
constructor(address _client) {
|
constructor(address client_) {
|
||||||
client = _client;
|
client = client_;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Forward call to "setOwner(address)" that is implemented by client
|
/// Forward call to "setOwner(address)" that is implemented by client
|
||||||
/// after doing basic validation on the address argument.
|
/// after doing basic validation on the address argument.
|
||||||
function forward(bytes calldata _payload) external {
|
function forward(bytes calldata payload) external {
|
||||||
bytes4 sig = bytes4(_payload[:4]);
|
bytes4 sig = bytes4(payload[:4]);
|
||||||
// Due to truncating behaviour, bytes4(_payload) performs identically.
|
// Due to truncating behaviour, bytes4(payload) performs identically.
|
||||||
// bytes4 sig = bytes4(_payload);
|
// bytes4 sig = bytes4(payload);
|
||||||
if (sig == bytes4(keccak256("setOwner(address)"))) {
|
if (sig == bytes4(keccak256("setOwner(address)"))) {
|
||||||
address owner = abi.decode(_payload[4:], (address));
|
address owner = abi.decode(payload[4:], (address));
|
||||||
require(owner != address(0), "Address of owner cannot be zero.");
|
require(owner != address(0), "Address of owner cannot be zero.");
|
||||||
}
|
}
|
||||||
(bool status,) = client.delegatecall(_payload);
|
(bool status,) = client.delegatecall(payload);
|
||||||
require(status, "Forwarded call failed.");
|
require(status, "Forwarded call failed.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user