mirror of https://github.com/status-im/EIPs.git
Update cache to use explicit return values of 32 byte length
This commit is contained in:
parent
50f59da47f
commit
529ce1b2ca
|
@ -36,11 +36,11 @@ For this standard, an *interface* is a set of [function selectors as calculated
|
||||||
We define the interface identifier as the XOR of all function selectors in the interface. This code example shows how to calculate an interface identifier:
|
We define the interface identifier as the XOR of all function selectors in the interface. This code example shows how to calculate an interface identifier:
|
||||||
|
|
||||||
```solidity
|
```solidity
|
||||||
pragma solidity ^0.4.19;
|
pragma solidity ^0.4.20;
|
||||||
|
|
||||||
interface Solidity101 {
|
interface Solidity101 {
|
||||||
function hello() public pure;
|
function hello() external pure;
|
||||||
function world(int) public pure;
|
function world(int) external pure;
|
||||||
}
|
}
|
||||||
|
|
||||||
contract Selector {
|
contract Selector {
|
||||||
|
@ -58,7 +58,7 @@ Note: interfaces do not permit optional functions, therefore, the interface iden
|
||||||
A contract that is compliant with ERC-165 shall implement the following interface (referred as `ERC165.sol`):
|
A contract that is compliant with ERC-165 shall implement the following interface (referred as `ERC165.sol`):
|
||||||
|
|
||||||
```solidity
|
```solidity
|
||||||
pragma solidity ^0.4.19;
|
pragma solidity ^0.4.20;
|
||||||
|
|
||||||
interface ERC165 {
|
interface ERC165 {
|
||||||
/// @notice Query if a contract implements an interface
|
/// @notice Query if a contract implements an interface
|
||||||
|
@ -113,7 +113,7 @@ Also [the ENS](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-137.md) alr
|
||||||
Following is a caching contract that detects which interfaces other contracts implement. From @fulldecent and @jbaylina.
|
Following is a caching contract that detects which interfaces other contracts implement. From @fulldecent and @jbaylina.
|
||||||
|
|
||||||
```solidity
|
```solidity
|
||||||
pragma solidity ^0.4.19;
|
pragma solidity ^0.4.20;
|
||||||
|
|
||||||
contract ERC165Cache {
|
contract ERC165Cache {
|
||||||
bytes4 constant InvalidID = 0xffffffff;
|
bytes4 constant InvalidID = 0xffffffff;
|
||||||
|
@ -139,25 +139,42 @@ contract ERC165Cache {
|
||||||
}
|
}
|
||||||
|
|
||||||
function determineInterfaceImplementationStatus(address _contract, bytes4 _interfaceId) internal view returns (ImplStatus) {
|
function determineInterfaceImplementationStatus(address _contract, bytes4 _interfaceId) internal view returns (ImplStatus) {
|
||||||
if (noThrowCall(_contract, InvalidID)) return ImplStatus.No;
|
uint256 success;
|
||||||
if (!noThrowCall(_contract, ERC165ID)) return ImplStatus.No;
|
uint256 result;
|
||||||
if (noThrowCall(_contract, _interfaceId)) return ImplStatus.Yes;
|
|
||||||
|
(success, result) = noThrowCall(_contract, ERC165ID);
|
||||||
|
if ((success==0)||(result==0)) {
|
||||||
return ImplStatus.No;
|
return ImplStatus.No;
|
||||||
}
|
}
|
||||||
|
|
||||||
function noThrowCall(address _contract, bytes4 _interfaceId) internal view returns (bool result) {
|
(success, result) = noThrowCall(_contract, InvalidID);
|
||||||
|
if ((success==0)||(result!=0)) {
|
||||||
|
return ImplStatus.No;
|
||||||
|
}
|
||||||
|
|
||||||
|
(success, result) = noThrowCall(_contract, _interfaceId);
|
||||||
|
if ((success==1)&&(result==1)) {
|
||||||
|
return ImplStatus.Yes;
|
||||||
|
}
|
||||||
|
return ImplStatus.No;
|
||||||
|
}
|
||||||
|
|
||||||
|
function noThrowCall(address _contract, bytes4 _interfaceId) constant internal returns (uint256 success, uint256 result) {
|
||||||
bytes4 erc165ID = ERC165ID;
|
bytes4 erc165ID = ERC165ID;
|
||||||
|
|
||||||
assembly {
|
assembly {
|
||||||
let x := mload(0x40) // Find empty storage location using "free memory pointer"
|
let x := mload(0x40) // Find empty storage location using "free memory pointer"
|
||||||
mstore(x, erc165ID) // Place signature at begining of empty storage
|
mstore(x, erc165ID) // Place signature at begining of empty storage
|
||||||
mstore(add(x, 0x04), _interfaceId) // Place first argument directly next to signature
|
mstore(add(x, 0x04), _interfaceId) // Place first argument directly next to signature
|
||||||
staticcall(30000, // 30k gas
|
|
||||||
|
success := staticcall(
|
||||||
|
30000, // 5k gas
|
||||||
_contract, // To addr
|
_contract, // To addr
|
||||||
x, // Inputs are stored at location x
|
x, // Inputs are stored at location x
|
||||||
0x8, // Inputs are 8 byes long
|
0x8, // Inputs are 8 byes long
|
||||||
x, // Store output over input (saves space)
|
x, // Store output over input (saves space)
|
||||||
0x20) // Outputs are 32 bytes long
|
0x20) // Outputs are 32 bytes long
|
||||||
pop // Discard call return value
|
|
||||||
result := mload(x) // Load the result
|
result := mload(x) // Load the result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue