Merge pull request #10223 from ethereum/strict-conversion

[BREAKING] Strict conversion
This commit is contained in:
chriseth 2020-12-03 18:06:42 +01:00 committed by GitHub
commit 9bb83ef82d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
59 changed files with 272 additions and 134 deletions

View File

@ -16,6 +16,7 @@ Breaking Changes:
* Code Generator: Use ``revert`` with error signature ``Panic(uint256)`` and error codes instead of invalid opcode on failing assertions.
* Type System: Explicit conversions from literals to integer type is as strict as implicit conversions.
* Type System: Explicit conversions from literals to enums are only allowed if the value fits in the enum.
* Type System: Explicit conversions between two types are disallowed if it changes more than one of sign, width or kind at the same time.
* Type System: Declarations with the name ``this``, ``super`` and ``_`` are disallowed, with the exception of public functions and events.
* Type System: Disallow ``type(super)``.
* Command Line Interface: JSON fields `abi`, `devdoc`, `userdoc` and `storage-layout` are now sub-objects rather than strings.

View File

@ -49,6 +49,28 @@ New Restrictions
3. Explicit conversions between literals and enums are only allowed if the literal can
represent a value in the enum.
* There are new restrictions on explicit type conversions. The conversion is only allowed when there
is at most one change in sign, width or type-category (``int``, ``address``, ``bytesNN``, etc.)
Let us use the notation ``T(S)`` to denote the explicit conversion ``T(x)``, where, ``T`` and
``S`` are types, and ``x`` is any arbitrary variable of type ``S``. An example of such a
disallowed conversion would be ``uint16(int8)`` since it changes both width (8 bits to 16 bits)
and sign (signed integer to unsigned integer). In order to do the conversion, one has to go
through an intermediate type. In the previous example, this would be ``uint16(uint8(int8))`` or
``uint16(int16(int8))``. Note that the two ways to convert will produce different results e.g.,
for ``-1``. The following are some examples of conversions that are disallowed by this rule.
- ``address(uint)`` and ``uint(address)``: converting both type-category and width. Replace this by
``address(uint160(uint))`` and ``uint(uint160(address))`` respectively.
- ``int80(bytes10)`` and ``bytes10(int80)``: converting both type-category and sign. Replace this by
``int80(uint80(bytes10))`` and ``bytes10(uint80(int80)`` respectively.
- ``Contract(uint)``: converting both type-category and width. Replace this by
``Contract(address(uint160(uint)))``.
These conversions were disallowed to avoid ambiguity. For example, in the expression ``uint16 x =
uint16(int8(-1))``, the value of ``x`` would depend on whether the sign or the width conversion
was applied first.
* Function call options can only be given once, i.e. ``c.f{gas: 10000}{value: 1}()`` is invalid and has to be changed to ``c.f{gas: 10000, value: 1}()``.
* The global functions ``log0``, ``log1``, ``log2``, ``log3`` and ``log4`` have been removed.

View File

@ -202,7 +202,7 @@ restrictions highly readable.
{
owner = _newOwner;
// just some example condition
if (uint(owner) & 0 == 1)
if (uint160(owner) & 0 == 1)
// This did not refund for Solidity
// before version 0.4.0.
return;

View File

@ -260,7 +260,7 @@ which only need to be created if there is a dispute.
// This complicated expression just tells you how the address
// can be pre-computed. It is just there for illustration.
// You actually only need ``new D{salt: salt}(arg)``.
address predictedAddress = address(uint(keccak256(abi.encodePacked(
address predictedAddress = address(uint160(uint(keccak256(abi.encodePacked(
byte(0xff),
address(this),
salt,
@ -268,7 +268,7 @@ which only need to be created if there is a dispute.
type(D).creationCode,
arg
))
))));
)))));
D d = new D{salt: salt}(arg);
require(address(d) == predictedAddress);

View File

@ -784,7 +784,7 @@ Another example that uses external function types::
contract OracleUser {
Oracle constant private ORACLE_CONST = Oracle(0x1234567); // known contract
Oracle constant private ORACLE_CONST = Oracle(address(0x00000000219ab540356cBB839Cbe05303d7705Fa)); // known contract
uint private exchangeRate;
function buySomething() public {

View File

@ -443,13 +443,19 @@ BoolResult AddressType::isImplicitlyConvertibleTo(Type const& _other) const
BoolResult AddressType::isExplicitlyConvertibleTo(Type const& _convertTo) const
{
if (_convertTo.category() == category())
if ((_convertTo.category() == category()) || isImplicitlyConvertibleTo(_convertTo))
return true;
else if (auto const* contractType = dynamic_cast<ContractType const*>(&_convertTo))
return (m_stateMutability >= StateMutability::Payable) || !contractType->isPayable();
return isImplicitlyConvertibleTo(_convertTo) ||
_convertTo.category() == Category::Integer ||
(_convertTo.category() == Category::FixedBytes && 160 == dynamic_cast<FixedBytesType const&>(_convertTo).numBytes() * 8);
else if (auto integerType = dynamic_cast<IntegerType const*>(&_convertTo))
return (!integerType->isSigned() && integerType->numBits() == 160);
else if (
(_convertTo.category() == Category::FixedBytes) &&
(160 == dynamic_cast<FixedBytesType const&>(_convertTo).numBytes() * 8)
)
return true;
return false;
}
string AddressType::toString(bool) const
@ -566,12 +572,20 @@ BoolResult IntegerType::isImplicitlyConvertibleTo(Type const& _convertTo) const
BoolResult IntegerType::isExplicitlyConvertibleTo(Type const& _convertTo) const
{
return _convertTo.category() == category() ||
_convertTo.category() == Category::Address ||
_convertTo.category() == Category::Contract ||
_convertTo.category() == Category::Enum ||
(_convertTo.category() == Category::FixedBytes && numBits() == dynamic_cast<FixedBytesType const&>(_convertTo).numBytes() * 8) ||
_convertTo.category() == Category::FixedPoint;
if (isImplicitlyConvertibleTo(_convertTo))
return true;
else if (auto integerType = dynamic_cast<IntegerType const*>(&_convertTo))
return (numBits() == integerType->numBits()) || (isSigned() == integerType->isSigned());
else if (_convertTo.category() == Category::Address)
return (!isSigned() && numBits() == 160);
else if (auto fixedBytesType = dynamic_cast<FixedBytesType const*>(&_convertTo))
return (!isSigned() && (numBits() == fixedBytesType->numBytes() * 8));
else if (dynamic_cast<EnumType const*>(&_convertTo))
return true;
else if (auto fixedPointType = dynamic_cast<FixedPointType const*>(&_convertTo))
return (isSigned() == fixedPointType->isSigned()) && (numBits() == fixedPointType->numBits());
return false;
}
TypeResult IntegerType::unaryOperatorResult(Token _operator) const
@ -972,10 +986,7 @@ BoolResult RationalNumberType::isExplicitlyConvertibleTo(Type const& _convertTo)
if (category == Category::FixedBytes)
return false;
else if (category == Category::Address)
{
if (isNegative() || isFractional() || integerType()->numBits() > 160)
return false;
}
return !(isNegative() || isFractional() || integerType()->numBits() > 160);
else if (category == Category::Integer)
return false;
else if (auto enumType = dynamic_cast<EnumType const*>(&_convertTo))
@ -1446,10 +1457,16 @@ BoolResult FixedBytesType::isImplicitlyConvertibleTo(Type const& _convertTo) con
BoolResult FixedBytesType::isExplicitlyConvertibleTo(Type const& _convertTo) const
{
return (_convertTo.category() == Category::Integer && numBytes() * 8 == dynamic_cast<IntegerType const&>(_convertTo).numBits()) ||
(_convertTo.category() == Category::Address && numBytes() == 20) ||
_convertTo.category() == Category::FixedPoint ||
_convertTo.category() == category();
if (_convertTo.category() == category())
return true;
else if (auto integerType = dynamic_cast<IntegerType const*>(&_convertTo))
return (!integerType->isSigned() && integerType->numBits() == numBytes() * 8);
else if (_convertTo.category() == Category::Address && numBytes() == 20)
return true;
else if (auto fixedPointType = dynamic_cast<FixedPointType const*>(&_convertTo))
return fixedPointType->numBits() == numBytes() * 8;
return false;
}
TypeResult FixedBytesType::unaryOperatorResult(Token _operator) const
@ -2674,7 +2691,11 @@ size_t EnumType::numberOfMembers() const
BoolResult EnumType::isExplicitlyConvertibleTo(Type const& _convertTo) const
{
return _convertTo == *this || _convertTo.category() == Category::Integer;
if (_convertTo == *this)
return true;
else if (auto integerType = dynamic_cast<IntegerType const*>(&_convertTo))
return !integerType->isSigned();
return false;
}
unsigned EnumType::memberValue(ASTString const& _member) const

View File

@ -61,7 +61,7 @@ contract ScalarEvent is Event {
convertedWinningOutcome = OUTCOME_RANGE;
// Map outcome to outcome range
else
convertedWinningOutcome = uint24(OUTCOME_RANGE * (outcome - lowerBound) / (upperBound - lowerBound));
convertedWinningOutcome = uint24(uint(OUTCOME_RANGE * (outcome - lowerBound) / (upperBound - lowerBound)));
uint factorShort = OUTCOME_RANGE - convertedWinningOutcome;
uint factorLong = OUTCOME_RANGE - factorShort;
uint shortOutcomeTokenCount = outcomeTokens[SHORT].balanceOf(msg.sender);

View File

@ -103,19 +103,19 @@ contract multiowned {
// as well as the selection of addresses capable of confirming them.
constructor(address[] memory _owners, uint _required) {
m_numOwners = _owners.length + 1;
m_owners[1] = uint(msg.sender);
m_ownerIndex[uint(msg.sender)] = 1;
m_owners[1] = uint160(msg.sender);
m_ownerIndex[uint160(msg.sender)] = 1;
for (uint i = 0; i < _owners.length; ++i)
{
m_owners[2 + i] = uint(_owners[i]);
m_ownerIndex[uint(_owners[i])] = 2 + i;
m_owners[2 + i] = uint160(_owners[i]);
m_ownerIndex[uint160(_owners[i])] = 2 + i;
}
m_required = _required;
}
// Revokes a prior confirmation of the given operation
function revoke(bytes32 _operation) external {
uint ownerIndex = m_ownerIndex[uint(msg.sender)];
uint ownerIndex = m_ownerIndex[uint160(msg.sender)];
// make sure they're an owner
if (ownerIndex == 0) return;
uint ownerIndexBit = 2**ownerIndex;
@ -130,13 +130,13 @@ contract multiowned {
// Replaces an owner `_from` with another `_to`.
function changeOwner(address _from, address _to) onlymanyowners(keccak256(msg.data)) public virtual {
if (isOwner(_to)) return;
uint ownerIndex = m_ownerIndex[uint(_from)];
uint ownerIndex = m_ownerIndex[uint160(_from)];
if (ownerIndex == 0) return;
clearPending();
m_owners[ownerIndex] = uint(_to);
m_ownerIndex[uint(_from)] = 0;
m_ownerIndex[uint(_to)] = ownerIndex;
m_owners[ownerIndex] = uint160(_to);
m_ownerIndex[uint160(_from)] = 0;
m_ownerIndex[uint160(_to)] = ownerIndex;
emit OwnerChanged(_from, _to);
}
@ -149,18 +149,18 @@ contract multiowned {
if (m_numOwners >= c_maxOwners)
return;
m_numOwners++;
m_owners[m_numOwners] = uint(_owner);
m_ownerIndex[uint(_owner)] = m_numOwners;
m_owners[m_numOwners] = uint160(_owner);
m_ownerIndex[uint160(_owner)] = m_numOwners;
emit OwnerAdded(_owner);
}
function removeOwner(address _owner) onlymanyowners(keccak256(msg.data)) external {
uint ownerIndex = m_ownerIndex[uint(_owner)];
uint ownerIndex = m_ownerIndex[uint160(_owner)];
if (ownerIndex == 0) return;
if (m_required > m_numOwners - 1) return;
m_owners[ownerIndex] = 0;
m_ownerIndex[uint(_owner)] = 0;
m_ownerIndex[uint160(_owner)] = 0;
clearPending();
reorganizeOwners(); //make sure m_numOwner is equal to the number of owners and always points to the optimal free slot
emit OwnerRemoved(_owner);
@ -174,12 +174,12 @@ contract multiowned {
}
function isOwner(address _addr) public returns (bool) {
return m_ownerIndex[uint(_addr)] > 0;
return m_ownerIndex[uint160(_addr)] > 0;
}
function hasConfirmed(bytes32 _operation, address _owner) public view returns (bool) {
PendingState storage pending = m_pending[_operation];
uint ownerIndex = m_ownerIndex[uint(_owner)];
uint ownerIndex = m_ownerIndex[uint160(_owner)];
// make sure they're an owner
if (ownerIndex == 0) return false;
@ -197,7 +197,7 @@ contract multiowned {
function confirmAndCheck(bytes32 _operation) internal returns (bool) {
// determine what index the present sender is:
uint ownerIndex = m_ownerIndex[uint(msg.sender)];
uint ownerIndex = m_ownerIndex[uint160(msg.sender)];
// make sure they're an owner
if (ownerIndex == 0) return false;

View File

@ -34,7 +34,7 @@ function colony_test
FORCE_ABIv2=false
CONFIG="truffle.js"
truffle_setup https://github.com/solidity-external-tests/colonyNetwork.git develop_070
truffle_setup https://github.com/solidity-external-tests/colonyNetwork.git develop_080
run_install install_fn
cd lib

View File

@ -33,10 +33,10 @@ function gnosis_safe_test
OPTIMIZER_LEVEL=1
CONFIG="truffle.js"
truffle_setup https://github.com/solidity-external-tests/safe-contracts.git development_070
truffle_setup https://github.com/solidity-external-tests/safe-contracts.git development_080
force_truffle_version ^5.0.42
sed -i 's|github:gnosis/mock-contract#sol_0_5_0|github:solidity-external-tests/mock-contract#master_070|g' package.json
sed -i 's|github:gnosis/mock-contract#sol_0_5_0|github:solidity-external-tests/mock-contract#master_080|g' package.json
rm -f package-lock.json
rm -rf node_modules/

View File

@ -33,7 +33,7 @@ function zeppelin_test
OPTIMIZER_LEVEL=1
CONFIG="truffle-config.js"
truffle_setup https://github.com/solidity-external-tests/openzeppelin-contracts.git upgrade-0.7.0
truffle_setup https://github.com/solidity-external-tests/openzeppelin-contracts.git upgrade-0.8.0
run_install install_fn
truffle_run_test compile_fn test_fn

View File

@ -471,7 +471,7 @@ BOOST_AUTO_TEST_CASE(structs2)
s1[0].t[0].e = E.B;
s1[0].t[0].y = 0x12;
s2 = new S[](2);
s2[1].c = C(0x1234);
s2[1].c = C(address(0x1234));
s2[1].t = new T[](3);
s2[1].t[1].x = 0x21;
s2[1].t[1].e = E.C;

View File

@ -162,10 +162,10 @@ BOOST_AUTO_TEST_CASE(single_callvaluecheck)
a = b;
}
function f1(address b) public pure returns (uint c) {
return uint(b) + 2;
return uint160(b) + 2;
}
function f2(address b) public pure returns (uint) {
return uint(b) + 8;
return uint160(b) + 8;
}
function f3(address, uint c) pure public returns (uint) {
return c - 5;
@ -178,10 +178,10 @@ BOOST_AUTO_TEST_CASE(single_callvaluecheck)
a = b;
}
function f1(address b) public pure returns (uint c) {
return uint(b) + 2;
return uint160(b) + 2;
}
function f2(address b) public pure returns (uint) {
return uint(b) + 8;
return uint160(b) + 8;
}
function f3(address, uint c) payable public returns (uint) {
return c - 5;

View File

@ -673,9 +673,9 @@ BOOST_AUTO_TEST_CASE(sign_extension)
contract test {
function run() public returns(uint256 y) {
unchecked {
int64 x = -int32(0xff);
int64 x = -int32(int64(0xff));
if (x >= 0xff) return 0;
return 0 - uint256(x);
return 0 - uint256(int256(x));
}
}
}
@ -5683,7 +5683,7 @@ BOOST_AUTO_TEST_CASE(dirty_scratch_space_prior_to_constant_optimiser)
return 0x0000000000001234123412431234123412412342112341234124312341234124;
}
function g(address a) internal pure returns (uint) {
unchecked { return uint(a) * 0x0000000000001234123412431234123412412342112341234124312341234124; }
unchecked { return uint(uint160(a)) * 0x0000000000001234123412431234123412412342112341234124312341234124; }
}
function h(uint a) internal pure returns (uint) {
unchecked { return a * 0x0000000000001234123412431234123412412342112341234124312341234124; }

View File

@ -437,7 +437,7 @@ BOOST_AUTO_TEST_CASE(constant_optimization_early_exit)
char const* sourceCode = R"(
contract HexEncoding {
function hexEncodeTest(address addr) public returns (bytes32 ret) {
uint x = uint(addr) / 2**32;
uint x = uint(uint160(addr)) / 2**32;
// Nibble interleave
x = x & 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff;
@ -457,7 +457,7 @@ BOOST_AUTO_TEST_CASE(constant_optimization_early_exit)
assembly {
mstore(0, x)
}
x = uint(addr) * 2**96;
x = uint160(addr) * 2**96;
// Nibble interleave
x = x & 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff;

View File

@ -7,7 +7,7 @@ contract c {
for (uint8 i = 0; i <= 40; i++)
data.push(byte(i+1));
for (int8 j = 40; j >= 0; j--) {
require(data[uint8(j)] == byte(j+1));
require(data[uint8(j)] == byte(uint8(j+1)));
require(data.length == uint8(j+1));
data.pop();
}

View File

@ -1,6 +1,6 @@
contract C {
function f(int16[] calldata a) external returns (bool correct) {
uint32 x = uint32(a[1]);
uint32 x = uint32(uint16(a[1]));
uint r;
assembly {
r := x

View File

@ -4,7 +4,7 @@ abstract contract D {
contract C {
D d = D(0x1212);
D d = D(address(0x1212));
function f() public returns (uint256) {
d.g();

View File

@ -1,7 +1,7 @@
contract C {
function f() external {}
function g() external {
C c = C(0x0000000000000000000000000000000000000000000000000000000000000000);
C c = C(address(0x0000000000000000000000000000000000000000000000000000000000000000));
c.f();
}
}

View File

@ -13,9 +13,9 @@ contract C {
b = (0 - uint8(a)) * 2;
c = a * int8(120) * int8(121);
}
x1 = uint256(a);
x1 = uint256(int256(a));
x2 = b;
x3 = uint256(c);
x3 = uint256(int256(c));
x4 = d;
}
}

View File

@ -1,5 +1,5 @@
contract Test {
function test() public returns (uint ret) { return uint(address(uint128(type(uint200).max))); }
function test() public returns (uint ret) { return uint(uint160(address(uint160(uint128(type(uint200).max))))); }
}
// ====
// compileViaYul: also

View File

@ -9,9 +9,9 @@ contract C1 {
contract C {
function test() public returns (C1 x, C1 y) {
C1 c = new C1(C1(9));
C1 c = new C1(C1(address(9)));
x = c.bla();
y = this.t1(C1(7));
y = this.t1(C1(address(7)));
}
function t1(C1 a) public returns (C1) {
@ -19,7 +19,7 @@ contract C {
}
function t2() public returns (C1) {
return C1(9);
return C1(address(9));
}
}

View File

@ -4,7 +4,7 @@ contract C {
uint16[] m;
}
function f(S calldata s) public pure returns (bool correct) {
int8 x = int8(s.m[0]);
int8 x = int8(int16(s.m[0]));
uint r;
assembly {
r := x

View File

@ -4,7 +4,7 @@ contract C {
assembly {
mstore(m, 0xdeadbeef15dead)
}
int32 x = int32(m[0]);
int32 x = int32(uint32(m[0]));
uint r;
assembly {
r := x

View File

@ -21,19 +21,19 @@ contract C {
assert(x == 255);
// signed <- unsigned
int8 y = int8(type(uint16).max);
int8 y = int8(uint8(type(uint16).max));
assert(y == -1);
y = int8(uint16(100));
y = int8(uint8(uint16(100)));
assert(y == 100);
y = int8(uint16(200));
y = int8(uint8(uint16(200)));
assert(y == -56);
// unsigned <- signed
uint8 v = uint8(type(uint16).max);
assert(v == 255);
v = uint8(int16(300));
v = uint8(int8(int16(300)));
assert(v == 44);
v = uint8(int16(200));
v = uint8(int8(int16(200)));
assert(v == 200);
// fixed bytes

View File

@ -13,16 +13,16 @@ contract C {
assert(y == -(2**255) + 10);
int256 z = int256(uint(2**255 + 10));
assert(z == -(2**255) + 10);
int256 t = int256(bytes32(uint256(200)));
int256 t = int256(uint256(bytes32(uint256(200))));
assert(t == 200);
int256 v = int256(bytes32(uint256(2**255 + 10)));
int256 v = int256(uint256(bytes32(uint256(2**255 + 10))));
assert(v == -(2**255) + 10);
int160 a = int160(address(type(uint160).max));
int160 a = int160(uint160(address(type(uint160).max)));
assert(a == -1);
int160 b = int160(address(uint(2**159 + 10)));
int160 b = int160(uint160(address(uint160(uint(2**159 + 10)))));
assert(b == -(2**159) + 10);
D d;
int160 e = int160(address(d));
int160 e = int160(uint160(address(d)));
assert(e == 0);
}

View File

@ -9,28 +9,28 @@ contract C {
assert(x == 65535);
int8 i = int8(-1);
assert(i == -1);
x = uint16(int8(-1));
assert(x == 65535);
x = uint16(uint8(int8(-1)));
assert(x == 255);
x = uint16(int16(i));
assert(x == 65535);
uint z = uint(i);
assert(z == 2**256 - 1);
uint z = uint(uint8(i));
assert(z == 255);
}
function f2() public pure {
// signed <- unsigned
int16 y = int16(uint8(uint(65535)));
int16 y = int16(uint16(uint8(uint(65535))));
assert(y == 255);
int z = int(uint8(type(uint).max));
int z = int(uint(uint8(type(uint).max)));
assert(z == 255);
z = int(uint8(255));
z = int(uint(uint8(255)));
assert(z == 255);
}
function f3() public pure {
// signed <- signed
int16 y = int16(int8(uint(65535)));
assert(y == -1);
int16 y = int16(uint16(uint8(int8(int(uint(65535))))));
assert(y == 255);
int z = int(int8(-1));
assert(z == -1);
z = int(int8(int(255)));
@ -51,9 +51,9 @@ contract C {
assert(y == 65535);
y = uint16(uint8(type(uint16).max));
assert(y == 255);
address a = address(uint8(0));
address a = address(uint160(uint8(0)));
assert(a == address(0));
D d = D(uint8(0));
D d = D(address(uint160(uint8(0))));
assert(a == address(d));
bytes2 b1 = 0xcafe;
bytes4 b2 = bytes4(b1);

View File

@ -13,8 +13,8 @@ import "A";
contract Test {
function foo() public view {
C(0x00).set({_item: C.Item(50), _z: false, _y: "abc", _x: 30});
C(address(0x00)).set({_item: C.Item(50), _z: false, _y: "abc", _x: 30});
}
}
// ----
// TypeError 2443: (B:90-100): The type of this parameter, struct C.Item, is only supported in ABI coder v2. Use "pragma abicoder v2;" to enable the feature.
// TypeError 2443: (B:99-109): The type of this parameter, struct C.Item, is only supported in ABI coder v2. Use "pragma abicoder v2;" to enable the feature.

View File

@ -9,8 +9,8 @@ import "A";
contract D {
function g() public view {
C(0x00).f();
C(address(0x00)).f();
}
}
// ----
// TypeError 2428: (B:65-76): The type of return parameter 1, string[], is only supported in ABI coder v2. Use "pragma abicoder v2;" to enable the feature.
// TypeError 2428: (B:65-85): The type of return parameter 1, string[], is only supported in ABI coder v2. Use "pragma abicoder v2;" to enable the feature.

View File

@ -13,8 +13,8 @@ import "A";
contract Test {
function foo() public view {
C(0x00).get();
C(address(0x00)).get();
}
}
// ----
// TypeError 2428: (B:70-83): The type of return parameter 1, struct C.Item, is only supported in ABI coder v2. Use "pragma abicoder v2;" to enable the feature.
// TypeError 2428: (B:70-92): The type of return parameter 1, struct C.Item, is only supported in ABI coder v2. Use "pragma abicoder v2;" to enable the feature.

View File

@ -13,8 +13,8 @@ import "A";
contract Test {
function foo() public view {
C(0x00).get();
C(address(0x00)).get();
}
}
// ----
// TypeError 2428: (B:70-83): The type of return parameter 1, struct C.Item, is only supported in ABI coder v2. Use "pragma abicoder v2;" to enable the feature.
// TypeError 2428: (B:70-92): The type of return parameter 1, struct C.Item, is only supported in ABI coder v2. Use "pragma abicoder v2;" to enable the feature.

View File

@ -11,7 +11,7 @@ contract A {
contract B {
modifier validate() {
A(0x00).get();
A(address(0x00)).get();
_;
}
}

View File

@ -11,11 +11,11 @@ contract A {
contract B {
constructor() validate {
A(0x00).get();
A(address(0x00)).get();
}
modifier validate() {
A(0x00).get();
A(address(0x00)).get();
_;
}
}

View File

@ -11,11 +11,11 @@ contract A {
contract B {
constructor() {
A(0x00).get();
A(address(0x00)).get();
}
function foo() public view {
A(0x00).get();
A(address(0x00)).get();
}
}
==== Source: B ====

View File

@ -11,7 +11,7 @@ contract A {
contract B {
modifier validate() virtual {
A(0x00).get();
A(address(0x00)).get();
_;
}
}

View File

@ -35,7 +35,7 @@ import "X";
contract V2A {
modifier modV2A() {
X(0x00).get();
X(address(0x00)).get();
_;
}
}

View File

@ -11,7 +11,7 @@ import "A";
contract D {
function g() public view {
C(0x00).f();
C(address(0x00)).f();
}
}
// ----

View File

@ -15,7 +15,7 @@ import "A";
contract Test {
function foo() public view {
C(0x00).get();
C(address(0x00)).get();
}
}
// ----

View File

@ -15,7 +15,7 @@ import "A";
contract Test {
function foo() public view {
C(0x00).get();
C(address(0x00)).get();
}
}
// ----

View File

@ -13,7 +13,7 @@ import "A";
contract B {
modifier validate() {
A(0x00).get();
A(address(0x00)).get();
_;
}
}
@ -27,4 +27,4 @@ contract C is B {
{}
}
// ----
// TypeError 2428: (B:60-73): The type of return parameter 1, struct Data, is only supported in ABI coder v2. Use "pragma abicoder v2;" to enable the feature.
// TypeError 2428: (B:60-82): The type of return parameter 1, struct Data, is only supported in ABI coder v2. Use "pragma abicoder v2;" to enable the feature.

View File

@ -13,7 +13,7 @@ import "A";
contract B {
modifier validate() {
A(0x00).get();
A(address(0x00)).get();
_;
}
}
@ -29,4 +29,4 @@ contract C is B {
{}
}
// ----
// TypeError 2428: (B:60-73): The type of return parameter 1, struct Data, is only supported in ABI coder v2. Use "pragma abicoder v2;" to enable the feature.
// TypeError 2428: (B:60-82): The type of return parameter 1, struct Data, is only supported in ABI coder v2. Use "pragma abicoder v2;" to enable the feature.

View File

@ -2,12 +2,12 @@
contract A { constructor(string memory) { } }
contract B is A {
function f() pure public {
A x = A(0); // convert from address
A x = A(address(0)); // convert from address
string memory y = "ab";
A(y); // call as a function is invalid
x;
}
}
// ----
// TypeError 3656: (124-294): Contract "B" should be marked as abstract.
// TypeError 9640: (243-247): Explicit type conversion not allowed from "string memory" to "contract A".
// TypeError 3656: (124-303): Contract "B" should be marked as abstract.
// TypeError 9640: (252-256): Explicit type conversion not allowed from "string memory" to "contract A".

View File

@ -1,4 +1,4 @@
==== Source: a ====
contract A {}
==== Source: dir/a/b/c ====
import "../../.././a" as x; contract B is x.A { fallback() external { x.A r = x.A(20); r; } }
import "../../.././a" as x; contract B is x.A { fallback() external { x.A r = x.A(address(20)); r; } }

View File

@ -1,12 +1,12 @@
contract First {
function fun() public returns (bool) {
return Second(1).fun(1, true, 3) > 0;
return Second(address(1)).fun(1, true, 3) > 0;
}
}
contract Second {
function fun(uint, bool, uint) public returns (uint) {
if (First(2).fun() == true) return 1;
if (First(address(2)).fun() == true) return 1;
}
}
// ----
// Warning 6321: (183-187): Unnamed return variable can remain unassigned. Add an explicit return with value to all non-reverting code paths or name the variable.
// Warning 6321: (192-196): Unnamed return variable can remain unassigned. Add an explicit return with value to all non-reverting code paths or name the variable.

View File

@ -1,4 +1,4 @@
contract A { function f() public virtual { uint8 x = C(0).g(); } }
contract A { function f() public virtual { uint8 x = C(address(0)).g(); } }
contract B { function f() public virtual {} function g() public returns (uint8) {} }
contract C is A, B { function f() public override (A, B) { A.f(); } }
// ----

View File

@ -1,7 +1,7 @@
contract A { }
contract B is A {
function f() public { A a = B(1); }
function f() public { A a = B(address(1)); }
}
// ----
// Warning 2072: (59-62): Unused local variable.
// Warning 2018: (37-72): Function state mutability can be restricted to pure
// Warning 2018: (37-81): Function state mutability can be restricted to pure

View File

@ -1,6 +1,6 @@
contract A { }
contract B is A {
function f() public { B b = A(1); }
function f() public { B b = A(address(1)); }
}
// ----
// TypeError 9574: (59-69): Type contract A is not implicitly convertible to expected type contract B.
// TypeError 9574: (59-78): Type contract A is not implicitly convertible to expected type contract B.

View File

@ -2,6 +2,6 @@ contract c {
function f() public {}
}
contract d {
function g() public { c(0).f(); }
function g() public { c(address(0)).f(); }
}
// ----

View File

@ -2,7 +2,7 @@ contract c {
function f() internal {}
}
contract d {
function g() public { c(0).f(); }
function g() public { c(address(0)).f(); }
}
// ----
// TypeError 9582: (83-89): Member "f" not found or not visible after argument-dependent lookup in contract c.
// TypeError 9582: (83-98): Member "f" not found or not visible after argument-dependent lookup in contract c.

View File

@ -2,7 +2,7 @@ contract c {
uint a;
}
contract d {
function g() public { c(0).a(); }
function g() public { c(address(0)).a(); }
}
// ----
// TypeError 9582: (66-72): Member "a" not found or not visible after argument-dependent lookup in contract c.
// TypeError 9582: (66-81): Member "a" not found or not visible after argument-dependent lookup in contract c.

View File

@ -2,7 +2,7 @@ contract c {
uint public a;
}
contract d {
function g() public { c(0).a(); }
function g() public { c(address(0)).a(); }
}
// ----
// Warning 2018: (51-84): Function state mutability can be restricted to view
// Warning 2018: (51-93): Function state mutability can be restricted to view

View File

@ -1,3 +1,3 @@
contract C {
C constant x = C(0x123);
C constant x = C(address(0x123));
}

View File

@ -1,5 +1,5 @@
contract c {
modifier mod1(uint a) { if (msg.sender == address(a)) _; }
modifier mod1(uint a) { if (msg.sender == address(uint160(a))) _; }
modifier mod2 { if (msg.sender == address(2)) _; }
function f() public mod1(7) mod2 { }
}

View File

@ -1,5 +1,5 @@
contract C {
function f(uint x) public pure returns (address payable) {
return address(x);
return address(uint160(x));
}
}

View File

@ -256,7 +256,7 @@ contract Main {
A constant JU = JV;
A constant JV = JW;
A constant JW = JX;
A constant JX = A(0x00);
A constant JX = A(address(0x00));
}
// ----
// DeclarationError 7380: (6105-6123): Variable definition exhausting cyclic dependency validator.

View File

@ -131,5 +131,5 @@ contract Main {
A constant EZ = FA;
A constant FA = FB;
A constant FB = FC;
A constant FC = A(0x00);
A constant FC = A(address(0x00));
}

View File

@ -0,0 +1,42 @@
contract B{}
contract C
{
function f() public pure {
uint16 a = uint16(uint8(int8(-1)));
a;
int8 b = -1;
b;
uint16 c = uint16(uint8(b));
c;
int8 d = int8(int16(uint16(type(uint16).max)));
d;
uint16 e = type(uint16).max;
e;
int8 g = int8(uint8(e));
g;
address h = address(uint160(uint(type(uint).max)));
h;
uint i = uint(uint160(address(0)));
i;
uint j = type(uint).max;
j;
address k = address(uint160(j));
k;
int80 l = int80(uint80(bytes10("h")));
l;
bytes10 m = bytes10(uint80(int80(-1)));
m;
B n = B(address(uint160(uint(int(100)))));
n;
}
}
// ----

View File

@ -0,0 +1,52 @@
contract B{}
enum E { Zero }
contract C
{
function f() public pure {
uint16 a = uint16(int8(-1));
int8 b = -1;
uint16 c = uint16(b);
int8 d = int8(uint16(type(uint16).max));
uint16 e = type(uint16).max;
int8 g = int8(e);
address h = address(uint(type(uint).max));
uint i = uint(address(0));
uint j = type(uint).max;
address k = address(j);
int80 l = int80(bytes10("h"));
bytes10 m = bytes10(int80(-1));
B n = B(int(100));
int o = int(new B());
B p = B(0x00);
int q = int(E(0));
int r = int(E.Zero);
}
}
// ----
// TypeError 9640: (95-111): Explicit type conversion not allowed from "int8" to "uint16".
// TypeError 9640: (154-163): Explicit type conversion not allowed from "int8" to "uint16".
// TypeError 9640: (183-213): Explicit type conversion not allowed from "uint16" to "int8".
// TypeError 9640: (270-277): Explicit type conversion not allowed from "uint16" to "int8".
// TypeError 9640: (300-329): Explicit type conversion not allowed from "uint256" to "address".
// TypeError 9640: (349-365): Explicit type conversion not allowed from "address payable" to "uint256".
// TypeError 9640: (421-431): Explicit type conversion not allowed from "uint256" to "address".
// TypeError 9640: (452-471): Explicit type conversion not allowed from "bytes10" to "int80".
// TypeError 9640: (493-511): Explicit type conversion not allowed from "int80" to "bytes10".
// TypeError 9640: (528-539): Explicit type conversion not allowed from "int256" to "contract B".
// TypeError 9640: (557-569): Explicit type conversion not allowed from "contract B" to "int256".
// TypeError 9640: (586-593): Explicit type conversion not allowed from "int_const 0" to "contract B".
// TypeError 9640: (612-621): Explicit type conversion not allowed from "enum E" to "int256".
// TypeError 9640: (639-650): Explicit type conversion not allowed from "enum E" to "int256".

View File

@ -3,7 +3,7 @@ contract C {
return this;
}
function g() pure public returns (bytes4) {
C x = C(0x123);
C x = C(address(0x123));
return x.f.selector;
}
}