mirror of https://github.com/nucypher/nucypher.git
Test example of avoiding some compiler changes
parent
da3ce7b185
commit
509bc7ceec
|
@ -50,6 +50,7 @@ def test_dispatcher(testerchain):
|
|||
contract1_lib, _ = testerchain.interface.deploy_contract('ContractV1', 1)
|
||||
contract2_lib, _ = testerchain.interface.deploy_contract('ContractV2', 1)
|
||||
contract3_lib, _ = testerchain.interface.deploy_contract('ContractV3', 2)
|
||||
contract4_lib, _ = testerchain.interface.deploy_contract('ContractV4', 3)
|
||||
contract2_bad_storage_lib, _ = testerchain.interface.deploy_contract('ContractV2BadStorage')
|
||||
dispatcher, _ = testerchain.interface.deploy_contract('Dispatcher', contract1_lib.address, secret_hash)
|
||||
assert contract1_lib.address == dispatcher.functions.target().call()
|
||||
|
@ -322,7 +323,7 @@ def test_dispatcher(testerchain):
|
|||
tx = dispatcher.functions.upgrade(contract3_lib.address, secret, secret2_hash).transact({'from': creator})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
contract_instance = testerchain.interface.w3.eth.contract(
|
||||
abi=contract2_lib.abi,
|
||||
abi=contract3_lib.abi,
|
||||
address=dispatcher.address,
|
||||
ContractFactoryClass=Contract)
|
||||
assert contract3_lib.address == dispatcher.functions.target().call()
|
||||
|
@ -344,6 +345,9 @@ def test_dispatcher(testerchain):
|
|||
assert 13 == contract_instance.functions.getStructureArrayValue2(0, 1).call()
|
||||
assert 2 == contract_instance.functions.storageValueToCheck().call()
|
||||
assert 'Hello' == contract_instance.functions.dynamicallySizedValue().call()
|
||||
tx = contract_instance.functions.setAnotherStorageValue(77).transact({'from': creator})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
assert 77 == contract_instance.functions.anotherStorageValue().call()
|
||||
|
||||
events = upgrades.get_all_entries()
|
||||
assert 4 == len(events)
|
||||
|
@ -393,6 +397,78 @@ def test_dispatcher(testerchain):
|
|||
assert 1 == len(events)
|
||||
assert 33 == events[0]['args']['value']
|
||||
|
||||
# Check upgrading to the contract with explicit storage slots
|
||||
tx = dispatcher.functions.upgrade(contract4_lib.address, secret2, secret3_hash).transact({'from': creator})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
contract_instance = testerchain.interface.w3.eth.contract(
|
||||
abi=contract4_lib.abi,
|
||||
address=dispatcher.address,
|
||||
ContractFactoryClass=Contract)
|
||||
assert contract4_lib.address == dispatcher.functions.target().call()
|
||||
assert 30 == contract_instance.functions.returnValue().call()
|
||||
assert 5 == contract_instance.functions.storageValue().call()
|
||||
assert 2 == contract_instance.functions.getArrayValueLength().call()
|
||||
assert 12 == contract_instance.functions.arrayValues(0).call()
|
||||
assert 232 == contract_instance.functions.arrayValues(1).call()
|
||||
assert 41 == contract_instance.functions.mappingValues(14).call()
|
||||
assert 31 == contract_instance.functions.mappingValues(13).call()
|
||||
assert 3 == contract_instance.functions.arrayStructures(0).call()
|
||||
assert 4 == contract_instance.functions.arrayStructures(1).call()
|
||||
assert 11 == contract_instance.functions.getStructureArrayValue1(0, 0).call()
|
||||
assert 111 == contract_instance.functions.getStructureArrayValue1(0, 1).call()
|
||||
assert 12 == contract_instance.functions.getStructureArrayValue1(0, 2).call()
|
||||
assert [4, 55] == contract_instance.functions.mappingStructures(0).call()
|
||||
assert [5, 0] == contract_instance.functions.mappingStructures(1).call()
|
||||
assert 12 == contract_instance.functions.getStructureArrayValue2(0, 0).call()
|
||||
assert 13 == contract_instance.functions.getStructureArrayValue2(0, 1).call()
|
||||
assert 3 == contract_instance.functions.storageValueToCheck().call()
|
||||
assert 'Hello' == contract_instance.functions.dynamicallySizedValue().call()
|
||||
assert 77 == contract_instance.functions.anotherStorageValue().call()
|
||||
|
||||
events = state_verifications.get_all_entries()
|
||||
assert 10 == len(events)
|
||||
event_args = events[8]['args']
|
||||
assert contract4_lib.address == event_args['testTarget']
|
||||
assert creator == event_args['sender']
|
||||
assert event_args == events[9]['args']
|
||||
|
||||
events = upgrade_finishings.get_all_entries()
|
||||
assert 6 == len(events)
|
||||
event_args = events[5]['args']
|
||||
assert contract4_lib.address == event_args['target']
|
||||
assert creator == event_args['sender']
|
||||
|
||||
# Upgrade to the previous version - check that new `verifyState` can handle old contract
|
||||
tx = dispatcher.functions.upgrade(contract3_lib.address, secret3, secret_hash).transact({'from': creator})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
assert contract3_lib.address == dispatcher.functions.target().call()
|
||||
assert 20 == contract_instance.functions.returnValue().call()
|
||||
assert 5 == contract_instance.functions.storageValue().call()
|
||||
assert 2 == contract_instance.functions.getArrayValueLength().call()
|
||||
assert 12 == contract_instance.functions.arrayValues(0).call()
|
||||
assert 232 == contract_instance.functions.arrayValues(1).call()
|
||||
assert 41 == contract_instance.functions.mappingValues(14).call()
|
||||
assert 31 == contract_instance.functions.mappingValues(13).call()
|
||||
assert 3 == contract_instance.functions.arrayStructures(0).call()
|
||||
assert 4 == contract_instance.functions.arrayStructures(1).call()
|
||||
assert 11 == contract_instance.functions.getStructureArrayValue1(0, 0).call()
|
||||
assert 111 == contract_instance.functions.getStructureArrayValue1(0, 1).call()
|
||||
assert 12 == contract_instance.functions.getStructureArrayValue1(0, 2).call()
|
||||
assert [4, 55] == contract_instance.functions.mappingStructures(0).call()
|
||||
assert [5, 0] == contract_instance.functions.mappingStructures(1).call()
|
||||
assert 12 == contract_instance.functions.getStructureArrayValue2(0, 0).call()
|
||||
assert 13 == contract_instance.functions.getStructureArrayValue2(0, 1).call()
|
||||
assert 2 == contract_instance.functions.storageValueToCheck().call()
|
||||
assert 'Hello' == contract_instance.functions.dynamicallySizedValue().call()
|
||||
assert 77 == contract_instance.functions.anotherStorageValue().call()
|
||||
|
||||
events = state_verifications.get_all_entries()
|
||||
assert 12 == len(events)
|
||||
event_args = events[10]['args']
|
||||
assert contract3_lib.address == event_args['testTarget']
|
||||
assert creator == event_args['sender']
|
||||
assert event_args == events[11]['args']
|
||||
|
||||
|
||||
@pytest.mark.slow
|
||||
def test_selfdestruct(testerchain):
|
||||
|
|
|
@ -107,6 +107,8 @@ contract ContractV1 is Upgradeable {
|
|||
super.verifyState(_testTarget);
|
||||
require(delegateGet(_testTarget, "storageValue()") == storageValue);
|
||||
bytes memory value = delegateGetBytes(_testTarget, "dynamicallySizedValue()");
|
||||
// WARNING: sometimes execution of keccak256(string storage) on a long string (more than 31 bytes)
|
||||
// leads to out of gas or exception
|
||||
require(value.length == bytes(dynamicallySizedValue).length &&
|
||||
keccak256(value) == keccak256(bytes(dynamicallySizedValue)));
|
||||
|
||||
|
@ -121,8 +123,8 @@ contract ContractV1 is Upgradeable {
|
|||
|
||||
require(delegateGet(_testTarget, "getStructureLength1()") == arrayStructures.length);
|
||||
for (uint256 i = 0; i < arrayStructures.length; i++) {
|
||||
Structure1 memory structure1 = delegateGetStructure1(_testTarget, "arrayStructures(uint256)", bytes32(i));
|
||||
require(structure1.value == arrayStructures[i].value);
|
||||
require(delegateGet(_testTarget, "arrayStructures(uint256)", bytes32(i)) == arrayStructures[i].value);
|
||||
|
||||
require(delegateGet(_testTarget, "getStructureArrayLength1(uint256)", bytes32(i)) ==
|
||||
arrayStructures[i].arrayValues.length);
|
||||
for (uint256 j = 0; j < arrayStructures[i].arrayValues.length; j++) {
|
||||
|
@ -134,8 +136,8 @@ contract ContractV1 is Upgradeable {
|
|||
|
||||
require(delegateGet(_testTarget, "getStructureLength2()") == mappingStructuresLength);
|
||||
for (uint256 i = 0; i < mappingStructuresLength; i++) {
|
||||
Structure2 memory structure2 = delegateGetStructure2(_testTarget, "mappingStructures(uint256)", bytes32(i));
|
||||
require(structure2.value == mappingStructures[i].value);
|
||||
require(delegateGet(_testTarget, "mappingStructures(uint256)", bytes32(i)) == mappingStructures[i].value);
|
||||
|
||||
require(delegateGet(_testTarget, "getStructureArrayLength2(uint256)", bytes32(i)) ==
|
||||
mappingStructures[i].arrayValues.length);
|
||||
for (uint256 j = 0; j < mappingStructures[i].arrayValues.length; j++) {
|
||||
|
@ -146,24 +148,6 @@ contract ContractV1 is Upgradeable {
|
|||
}
|
||||
}
|
||||
|
||||
function delegateGetStructure1(address _target, string memory _signature, bytes32 _argument)
|
||||
internal returns (Structure1 memory result)
|
||||
{
|
||||
bytes32 memoryAddress = delegateGetData(_target, _signature, 1, _argument, 0);
|
||||
assembly {
|
||||
result := memoryAddress
|
||||
}
|
||||
}
|
||||
|
||||
function delegateGetStructure2(address _target, string memory _signature, bytes32 _argument)
|
||||
internal returns (Structure2 memory result)
|
||||
{
|
||||
bytes32 memoryAddress = delegateGetData(_target, _signature, 1, _argument, 0);
|
||||
assembly {
|
||||
result := memoryAddress
|
||||
}
|
||||
}
|
||||
|
||||
function delegateGetBytes(address _target, string memory _signature)
|
||||
internal returns (bytes memory result)
|
||||
{
|
||||
|
|
|
@ -127,41 +127,31 @@ contract ContractV2 is Upgradeable {
|
|||
mappingValues[index]);
|
||||
}
|
||||
|
||||
require(uint256(delegateGet(_testTarget, "getStructureLength1()")) == arrayStructures.length);
|
||||
require(delegateGet(_testTarget, "getStructureLength1()") == arrayStructures.length);
|
||||
for (uint256 i = 0; i < arrayStructures.length; i++) {
|
||||
Structure1 memory structure1 = delegateGetStructure1(_testTarget, "arrayStructures(uint256)", bytes32(i));
|
||||
require(structure1.value == arrayStructures[i].value);
|
||||
require(delegateGet(_testTarget, "arrayStructures(uint256)", bytes32(i)) == arrayStructures[i].value);
|
||||
|
||||
bytes32[] memory values = delegateGetArray(_testTarget, "getStructure1ArrayValues(uint256)", bytes32(i));
|
||||
uint256[] memory values = delegateGetArray(_testTarget, "getStructure1ArrayValues(uint256)", bytes32(i));
|
||||
require(values.length == arrayStructures[i].arrayValues.length);
|
||||
for (uint256 j = 0; j < arrayStructures[i].arrayValues.length; j++) {
|
||||
require(uint256(values[j]) == arrayStructures[i].arrayValues[j]);
|
||||
require(values[j] == arrayStructures[i].arrayValues[j]);
|
||||
}
|
||||
}
|
||||
|
||||
require(uint256(delegateGet(_testTarget, "getStructureLength2()")) == mappingStructuresLength);
|
||||
require(delegateGet(_testTarget, "getStructureLength2()") == mappingStructuresLength);
|
||||
for (uint256 i = 0; i < mappingStructuresLength; i++) {
|
||||
Structure2 memory structure2 = delegateGetStructure2(_testTarget, "mappingStructures(uint256)", bytes32(i));
|
||||
require(structure2.value == mappingStructures[i].value);
|
||||
require(structure2.valueToCheck == mappingStructures[i].valueToCheck);
|
||||
|
||||
bytes32[] memory values = delegateGetArray(_testTarget, "getStructure2ArrayValues(uint256)", bytes32(i));
|
||||
uint256[] memory values = delegateGetArray(_testTarget, "getStructure2ArrayValues(uint256)", bytes32(i));
|
||||
require(values.length == mappingStructures[i].arrayValues.length);
|
||||
for (uint256 j = 0; j < mappingStructures[i].arrayValues.length; j++) {
|
||||
require(uint256(values[j]) == mappingStructures[i].arrayValues[j]);
|
||||
require(values[j] == mappingStructures[i].arrayValues[j]);
|
||||
}
|
||||
}
|
||||
|
||||
require(uint256(delegateGet(_testTarget, "storageValueToCheck()")) == storageValueToCheck);
|
||||
}
|
||||
|
||||
function delegateGetStructure1(address _target, string memory _signature, bytes32 _argument)
|
||||
internal returns (Structure1 memory result)
|
||||
{
|
||||
bytes32 memoryAddress = delegateGetData(_target, _signature, 1, _argument, 0);
|
||||
assembly {
|
||||
result := memoryAddress
|
||||
}
|
||||
require(delegateGet(_testTarget, "storageValueToCheck()") == storageValueToCheck);
|
||||
}
|
||||
|
||||
function delegateGetStructure2(address _target, string memory _signature, bytes32 _argument)
|
||||
|
@ -192,7 +182,7 @@ contract ContractV2 is Upgradeable {
|
|||
string memory _signature,
|
||||
bytes32 _argument
|
||||
)
|
||||
public returns (bytes32[] memory result)
|
||||
public returns (uint256[] memory result)
|
||||
{
|
||||
bytes32 memoryAddress = delegateGetData(_target, _signature, 1, _argument, 0);
|
||||
assembly {
|
||||
|
|
|
@ -15,7 +15,7 @@ contract ContractV3 is ContractV2 {
|
|||
}
|
||||
|
||||
function setAnotherStorageValue(uint256 _value) public {
|
||||
anotherStorageValue = _value * 2;
|
||||
anotherStorageValue = _value;
|
||||
}
|
||||
|
||||
function verifyState(address _testTarget) public {
|
||||
|
|
|
@ -0,0 +1,295 @@
|
|||
pragma solidity ^0.5.3;
|
||||
|
||||
|
||||
import "contracts/proxy/Upgradeable.sol";
|
||||
|
||||
|
||||
/**
|
||||
* @dev Same test contract with explicit storage slots:
|
||||
* The contract uses assembler code to access some storage variables instead of relying on the compiler
|
||||
* This demonstrates how to mitigate possible changes in the compiler while using the proxy pattern
|
||||
* Many methods are not optimized on purpose to increase readability
|
||||
**/
|
||||
contract ContractV4 is Upgradeable {
|
||||
|
||||
// slot allocation costs nothing
|
||||
/// uint256 public storageValue;
|
||||
uint256 reservedSlot5;
|
||||
/// string public dynamicallySizedValue;
|
||||
uint256 reservedSlot6;
|
||||
/// uint256[] public arrayValues;
|
||||
uint256 reservedSlot7;
|
||||
/// mapping (uint256 => uint256) public mappingValues;
|
||||
uint256 reservedSlot8;
|
||||
/// uint256[] public mappingIndices;
|
||||
uint256 reservedSlot9;
|
||||
|
||||
struct Structure1 {
|
||||
uint256 value;
|
||||
uint256[] arrayValues;
|
||||
}
|
||||
/// Structure1[] public arrayStructures;
|
||||
uint256 reservedSlot10;
|
||||
|
||||
struct Structure2 {
|
||||
uint256 value;
|
||||
uint256[] arrayValues;
|
||||
uint256 valueToCheck;
|
||||
}
|
||||
/// mapping (uint256 => Structure2) public mappingStructures;
|
||||
uint256 reservedSlot11;
|
||||
/// uint256 public mappingStructuresLength;
|
||||
uint256 reservedSlot12;
|
||||
|
||||
/// uint256 public storageValueToCheck;
|
||||
uint256 reservedSlot13;
|
||||
uint256 public anotherStorageValue;
|
||||
|
||||
constructor(uint256 _storageValueToCheck) public {
|
||||
setStorageValueToCheck(_storageValueToCheck);
|
||||
}
|
||||
|
||||
function returnValue() public pure returns (uint256) {
|
||||
return 30;
|
||||
}
|
||||
|
||||
|
||||
/// @dev Get data from the specified slot
|
||||
function getValue(uint256 _slotNumber) public view returns (uint256 value) {
|
||||
assembly {
|
||||
value := sload(_slotNumber)
|
||||
}
|
||||
}
|
||||
|
||||
/// @dev Array data is in the slot keccak256(_slotNumber)+_index
|
||||
function getArraySlot(uint256 _slotNumber, uint256 _index) private pure returns (uint256 slot) {
|
||||
assembly {
|
||||
// put data for hash into a free memory
|
||||
let memoryAddress := mload(0x40)
|
||||
mstore(memoryAddress, _slotNumber)
|
||||
let baseSlot := keccak256(memoryAddress, 32)
|
||||
slot := add(baseSlot, _index)
|
||||
}
|
||||
}
|
||||
function getArrayValue(uint256 _slotNumber, uint256 _index) private view returns (uint256 value) {
|
||||
return getValue(getArraySlot(_slotNumber, _index));
|
||||
}
|
||||
|
||||
/// @dev Mapping data is in the slot keccak256(concat(_index, _slotNumber))
|
||||
function getMappingSlot(uint256 _slotNumber, uint256 _index) private pure returns (uint256 slot) {
|
||||
assembly {
|
||||
let memoryAddress := mload(0x40)
|
||||
mstore(memoryAddress, _index)
|
||||
mstore(add(memoryAddress, 32), _slotNumber)
|
||||
slot := keccak256(memoryAddress, 64)
|
||||
}
|
||||
}
|
||||
function getMappingValue(uint256 _slotNumber, uint256 _index) private view returns (uint256 value) {
|
||||
return getValue(getMappingSlot(_slotNumber, _index));
|
||||
}
|
||||
|
||||
|
||||
function storageValue() public view returns (uint256 value) {
|
||||
// storageValue in the slot number 5
|
||||
return getValue(5);
|
||||
}
|
||||
|
||||
function dynamicallySizedValue() public view returns (string memory value) {
|
||||
uint256 slotValue = getValue(6);
|
||||
// https://solidity.readthedocs.io/en/latest/miscellaneous.html#bytes-and-string
|
||||
uint8 lowestBit = uint8(slotValue & 1);
|
||||
if (lowestBit == 0) {
|
||||
uint8 length = uint8(bytes32(slotValue)[31]) / 2;
|
||||
value = new string(length);
|
||||
assembly {
|
||||
mstore(add(value, 32), slotValue)
|
||||
mstore8(add(value, 63), 0)
|
||||
}
|
||||
} else {
|
||||
uint256 length = (slotValue - 1) / 2;
|
||||
value = new string(length);
|
||||
uint256 wordsCount = (length - 1) / 32 + 1;
|
||||
for (uint256 i = 0; i < wordsCount; i++) {
|
||||
uint256 word = getArrayValue(6, i);
|
||||
uint256 offset = 32 * (i + 1);
|
||||
assembly {
|
||||
mstore(add(value, offset), word)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getArrayValueLength() public view returns (uint256) {
|
||||
// length of the array in the slot number 7
|
||||
return getValue(7);
|
||||
}
|
||||
function arrayValues(uint256 _index) public view returns (uint256) {
|
||||
require(_index < getArrayValueLength());
|
||||
// base slot for this array is 7
|
||||
return getArrayValue(7, _index);
|
||||
}
|
||||
|
||||
|
||||
function mappingValues(uint256 _index) public view returns (uint256) {
|
||||
// base slot for this mapping is 8
|
||||
return getMappingValue(8, _index);
|
||||
}
|
||||
function getMappingIndicesLength() public view returns (uint256) {
|
||||
// length of the array in the slot number 9
|
||||
return getValue(9);
|
||||
}
|
||||
function mappingIndices(uint256 _index) public view returns (uint256) {
|
||||
require(_index < getMappingIndicesLength());
|
||||
return getArrayValue(9, _index);
|
||||
}
|
||||
|
||||
|
||||
function getStructureLength1() public view returns (uint256) {
|
||||
// length of the array in the slot number 10
|
||||
return getValue(10);
|
||||
}
|
||||
function arrayStructures(uint256 _index) public view returns (uint256) {
|
||||
require(_index < getStructureLength1());
|
||||
// base slot for this array is 10
|
||||
// one value in this array is `value` and the length of the inner `arrayValues`
|
||||
// so each index represents 2 slots
|
||||
return getArrayValue(10, 2 * _index);
|
||||
}
|
||||
function getStructureArrayLength1(uint256 _index) public view returns (uint256) {
|
||||
require(_index < getStructureLength1());
|
||||
// same as above except accessing second part of the value
|
||||
return getArrayValue(10, 2 * _index + 1);
|
||||
}
|
||||
/// @dev Array data is in the slot keccak256(keccak256(10) + 2 * _index + 1) + _arrayIndex
|
||||
function getStructureArrayValue1(uint256 _index, uint256 _arrayIndex) public view returns (uint256) {
|
||||
require(_arrayIndex < getStructureArrayLength1(_index));
|
||||
uint256 baseSlot = getArraySlot(10, 2 * _index + 1);
|
||||
return getArrayValue(baseSlot, _arrayIndex);
|
||||
}
|
||||
function getStructure1ArrayValues(uint256 _index) public view returns (uint256[] memory result) {
|
||||
result = new uint256[](getStructureArrayLength1(_index));
|
||||
uint256 baseSlot = getArraySlot(10, 2 * _index + 1);
|
||||
for (uint256 i = 0; i < result.length; i++) {
|
||||
result[i] = getArrayValue(baseSlot, i);
|
||||
}
|
||||
}
|
||||
|
||||
function getStructureLength2() public view returns (uint256) {
|
||||
return getValue(12);
|
||||
}
|
||||
function mappingStructures(uint256 _index) public view returns (uint256 value, uint256 valueToCheck) {
|
||||
uint256 baseMappingSlot = getMappingSlot(11, _index);
|
||||
// one mapping value is `value`, the length of the inner `arrayValues` and `valueToCheck`
|
||||
value = getValue(baseMappingSlot);
|
||||
valueToCheck = getValue(baseMappingSlot + 2);
|
||||
}
|
||||
function getStructureArrayLength2(uint256 _index) public view returns (uint256) {
|
||||
return getValue(getMappingSlot(11, _index) + 1);
|
||||
}
|
||||
/// @dev Array data is in the slot keccak256(keccak256(concat(_index, 11)) + 1) + _arrayIndex
|
||||
function getStructureArrayValue2(uint256 _index, uint256 _arrayIndex) public view returns (uint256) {
|
||||
require(_arrayIndex < getStructureArrayLength2(_index));
|
||||
uint256 baseArraySlot = getMappingSlot(11, _index) + 1;
|
||||
return getArrayValue(baseArraySlot, _arrayIndex);
|
||||
}
|
||||
function getStructure2ArrayValues(uint256 _index) public view returns (uint256[] memory result) {
|
||||
result = new uint256[](getStructureArrayLength2(_index));
|
||||
uint256 baseArraySlot = getMappingSlot(11, _index) + 1;
|
||||
for (uint256 i = 0; i < result.length; i++) {
|
||||
result[i] = getArrayValue(baseArraySlot, i);
|
||||
}
|
||||
}
|
||||
|
||||
function storageValueToCheck() public view returns (uint256) {
|
||||
return getValue(13);
|
||||
}
|
||||
function setStorageValueToCheck(uint256 _value) public {
|
||||
assembly {
|
||||
sstore(13, _value)
|
||||
}
|
||||
}
|
||||
|
||||
function verifyState(address _testTarget) public {
|
||||
super.verifyState(_testTarget);
|
||||
require(delegateGet(_testTarget, "storageValue()") == storageValue());
|
||||
bytes memory value = delegateGetBytes(_testTarget, "dynamicallySizedValue()");
|
||||
bytes memory originalValue = bytes(dynamicallySizedValue());
|
||||
require(value.length == originalValue.length &&
|
||||
keccak256(value) == keccak256(originalValue));
|
||||
|
||||
uint256 length = getArrayValueLength();
|
||||
require(delegateGet(_testTarget, "getArrayValueLength()") == length);
|
||||
for (uint256 i = 0; i < length; i++) {
|
||||
require(delegateGet(_testTarget, "arrayValues(uint256)", bytes32(i)) == arrayValues(i));
|
||||
}
|
||||
length = getMappingIndicesLength();
|
||||
for (uint256 i = 0; i < length; i++) {
|
||||
uint256 index = mappingIndices(i);
|
||||
require(delegateGet(_testTarget, "mappingValues(uint256)", bytes32(index)) == mappingValues(index));
|
||||
}
|
||||
|
||||
length = getStructureLength1();
|
||||
require(delegateGet(_testTarget, "getStructureLength1()") == length);
|
||||
for (uint256 i = 0; i < length; i++) {
|
||||
require(delegateGet(_testTarget, "arrayStructures(uint256)", bytes32(i)) == arrayStructures(i));
|
||||
|
||||
uint256 structuresLength = getStructureArrayLength1(i);
|
||||
require(delegateGet(_testTarget, "getStructureArrayLength1(uint256)", bytes32(i)) == structuresLength);
|
||||
for (uint256 j = 0; j < structuresLength; j++) {
|
||||
require(delegateGet(
|
||||
_testTarget, "getStructureArrayValue1(uint256,uint256)", bytes32(i), bytes32(j)) ==
|
||||
getStructureArrayValue1(i, j));
|
||||
}
|
||||
}
|
||||
|
||||
length = getStructureLength2();
|
||||
require(delegateGet(_testTarget, "getStructureLength2()") == length);
|
||||
for (uint256 i = 0; i < length; i++) {
|
||||
Structure2 memory structure2 = delegateGetStructure2(_testTarget, "mappingStructures(uint256)", bytes32(i));
|
||||
(uint256 structureValue, uint256 structureValueToCheck) = mappingStructures(i);
|
||||
require(structureValue == structure2.value && structureValueToCheck == structure2.valueToCheck);
|
||||
|
||||
uint256 structuresLength = getStructureArrayLength2(i);
|
||||
require(delegateGet(_testTarget, "getStructureArrayLength2(uint256)", bytes32(i)) == structuresLength);
|
||||
for (uint256 j = 0; j < structuresLength; j++) {
|
||||
require(delegateGet(
|
||||
_testTarget, "getStructureArrayValue2(uint256,uint256)", bytes32(i), bytes32(j)) ==
|
||||
getStructureArrayValue2(i, j));
|
||||
}
|
||||
}
|
||||
|
||||
require(delegateGet(_testTarget, "storageValueToCheck()") == storageValueToCheck());
|
||||
require(delegateGet(_testTarget, "anotherStorageValue()") == anotherStorageValue);
|
||||
}
|
||||
|
||||
function delegateGetStructure2(address _target, string memory _signature, bytes32 _argument)
|
||||
internal returns (Structure2 memory result)
|
||||
{
|
||||
bytes32 memoryAddress = delegateGetData(_target, _signature, 1, _argument, 0);
|
||||
assembly {
|
||||
mstore(result, mload(memoryAddress))
|
||||
mstore(add(result, 64), mload(add(memoryAddress, 32)))
|
||||
}
|
||||
}
|
||||
|
||||
function delegateGetBytes(address _target, string memory _signature)
|
||||
internal returns (bytes memory result)
|
||||
{
|
||||
bytes32 memoryAddress = delegateGetData(_target, _signature, 0, 0, 0);
|
||||
assembly {
|
||||
// weird problems with copying the memory pointer:
|
||||
// result := add(memoryAddress, mload(memoryAddress))
|
||||
|
||||
// quick fix for tests - copy the beginning of the array
|
||||
let start := add(memoryAddress, mload(memoryAddress))
|
||||
mstore(result, mload(start))
|
||||
mstore(add(result, 32), mload(add(start, 32)))
|
||||
}
|
||||
}
|
||||
|
||||
function finishUpgrade(address _target) public {
|
||||
super.finishUpgrade(_target);
|
||||
setStorageValueToCheck(ContractV4(_target).storageValueToCheck());
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue