Skip to content

Commit

Permalink
StarkEx v4.5
Browse files Browse the repository at this point in the history
  • Loading branch information
gkaempfer committed May 16, 2022
1 parent 01961a1 commit f4ed79b
Show file tree
Hide file tree
Showing 236 changed files with 37,529 additions and 10,045 deletions.
20 changes: 20 additions & 0 deletions common-contracts/src/interfaces/ContractInitializer.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// SPDX-License-Identifier: Apache-2.0.
pragma solidity ^0.6.12;

/**
Interface for contract initialization.
The functions it exposes are the app specific parts of the contract initialization,
and are called by the ProxySupport contract that implement the generic part of behind-proxy
initialization.
*/
abstract contract ContractInitializer {
function numOfSubContracts() internal pure virtual returns (uint256);

function isInitialized() internal view virtual returns (bool);

function validateInitData(bytes calldata data) internal pure virtual;

function processSubContractAddresses(bytes calldata subContractAddresses) internal virtual;

function initializeContractState(bytes calldata data) internal virtual;
}
1 change: 1 addition & 0 deletions common-contracts/src/interfaces/ExternalInitializer.sol
78 changes: 78 additions & 0 deletions common-contracts/src/interfaces/ProxySupport.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// SPDX-License-Identifier: Apache-2.0.
pragma solidity ^0.6.12;

import "../components/Governance.sol";
import "../libraries/Common.sol";
import "./BlockDirectCall.sol";
import "./ContractInitializer.sol";

/**
This contract contains the code commonly needed for a contract to be deployed behind
an upgradability proxy.
It perform the required semantics of the proxy pattern,
but in a generic manner.
Instantiation of the Governance and of the ContractInitializer, that are the app specific
part of initialization, has to be done by the using contract.
*/
abstract contract ProxySupport is Governance, BlockDirectCall, ContractInitializer {
using Addresses for address;

// The two function below (isFrozen & initialize) needed to bind to the Proxy.
function isFrozen() external view virtual returns (bool) {
return false;
}

/*
The initialize() function serves as an alternative constructor for a proxied deployment.
Flow and notes:
1. This function cannot be called directly on the deployed contract, but only via
delegate call.
2. If an EIC is provided - init is passed onto EIC and the standard init flow is skipped.
This true for both first intialization or a later one.
3. The data passed to this function is as follows:
[sub_contracts addresses, eic address, initData].
When calling on an initialized contract (no EIC scenario), initData.length must be 0.
*/
function initialize(bytes calldata data) external notCalledDirectly {
uint256 eicOffset = 32 * numOfSubContracts();
uint256 expectedBaseSize = eicOffset + 32;
require(data.length >= expectedBaseSize, "INIT_DATA_TOO_SMALL");
address eicAddress = abi.decode(data[eicOffset:expectedBaseSize], (address));

bytes calldata subContractAddresses = data[:eicOffset];

processSubContractAddresses(subContractAddresses);

bytes calldata initData = data[expectedBaseSize:];

// EIC Provided - Pass initData to EIC and the skip standard init flow.
if (eicAddress != address(0x0)) {
callExternalInitializer(eicAddress, initData);
return;
}

if (isInitialized()) {
require(initData.length == 0, "UNEXPECTED_INIT_DATA");
} else {
// Contract was not initialized yet.
validateInitData(initData);
initializeContractState(initData);
initGovernance();
}
}

function callExternalInitializer(address externalInitializerAddr, bytes calldata eicData)
private
{
require(externalInitializerAddr.isContract(), "EIC_NOT_A_CONTRACT");

// NOLINTNEXTLINE: low-level-calls, controlled-delegatecall.
(bool success, bytes memory returndata) = externalInitializerAddr.delegatecall(
abi.encodeWithSelector(this.initialize.selector, eicData)
);
require(success, string(returndata));
require(returndata.length == 0, string(returndata));
}
}
105 changes: 105 additions & 0 deletions common-contracts/src/libraries/NamedStorage.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
// SPDX-License-Identifier: Apache-2.0.
pragma solidity ^0.6.12;

/*
Library to provide basic storage, in storage location out of the low linear address space.
New types of storage variables should be added here upon need.
*/
library NamedStorage {
function bytes32ToUint256Mapping(string memory tag_)
internal
pure
returns (mapping(bytes32 => uint256) storage randomVariable)
{
bytes32 location = keccak256(abi.encodePacked(tag_));
assembly {
randomVariable_slot := location
}
}

function bytes32ToAddressMapping(string memory tag_)
internal
pure
returns (mapping(bytes32 => address) storage randomVariable)
{
bytes32 location = keccak256(abi.encodePacked(tag_));
assembly {
randomVariable_slot := location
}
}

function uintToAddressMapping(string memory tag_)
internal
pure
returns (mapping(uint256 => address) storage randomVariable)
{
bytes32 location = keccak256(abi.encodePacked(tag_));
assembly {
randomVariable_slot := location
}
}

function addressToBoolMapping(string memory tag_)
internal
pure
returns (mapping(address => bool) storage randomVariable)
{
bytes32 location = keccak256(abi.encodePacked(tag_));
assembly {
randomVariable_slot := location
}
}

function getUintValue(string memory tag_) internal view returns (uint256 retVal) {
bytes32 slot = keccak256(abi.encodePacked(tag_));
assembly {
retVal := sload(slot)
}
}

function setUintValue(string memory tag_, uint256 value) internal {
bytes32 slot = keccak256(abi.encodePacked(tag_));
assembly {
sstore(slot, value)
}
}

function setUintValueOnce(string memory tag_, uint256 value) internal {
require(getUintValue(tag_) == 0, "ALREADY_SET");
setUintValue(tag_, value);
}

function getAddressValue(string memory tag_) internal view returns (address retVal) {
bytes32 slot = keccak256(abi.encodePacked(tag_));
assembly {
retVal := sload(slot)
}
}

function setAddressValue(string memory tag_, address value) internal {
bytes32 slot = keccak256(abi.encodePacked(tag_));
assembly {
sstore(slot, value)
}
}

function setAddressValueOnce(string memory tag_, address value) internal {
require(getAddressValue(tag_) == address(0x0), "ALREADY_SET");
setAddressValue(tag_, value);
}

function getBoolValue(string memory tag_) internal view returns (bool retVal) {
bytes32 slot = keccak256(abi.encodePacked(tag_));
assembly {
retVal := sload(slot)
}
}

function setBoolValue(string memory tag_, bool value) internal {
bytes32 slot = keccak256(abi.encodePacked(tag_));
assembly {
sstore(slot, value)
}
}
}
89 changes: 43 additions & 46 deletions common-contracts/src/upgrade/CallProxy.sol
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
// SPDX-License-Identifier: Apache-2.0.
pragma solidity ^0.6.11;
pragma solidity ^0.6.12;

import "../interfaces/ContractInitializer.sol";
import "../interfaces/IFactRegistry.sol";
import "../interfaces/ProxySupport.sol";
import "./StorageSlots.sol";
import "../interfaces/BlockDirectCall.sol";
import "../libraries/Common.sol";

/**
Expand All @@ -16,67 +17,63 @@ import "../libraries/Common.sol";
thus:
1. Implementation address is stored in a hashed slot (other than proxy's one...).
2. No state variable is allowed in low address ranges.
3. Setting of implementation is done in initialize.
4. isFrozen and initialize are implemented, to be compliant with Proxy.
This implementation is intentionally minimal,
and has no management or governance.
The assumption is that if a different implementation is needed, it will be performed
in an upgradeTo a new deployed CallProxy, pointing to a new implementation.
*/
// NOLINTNEXTLINE locked-ether.
contract CallProxy is BlockDirectCall, StorageSlots {
contract CallProxy is StorageSlots, ContractInitializer, ProxySupport {
using Addresses for address;

string public constant CALL_PROXY_VERSION = "3.1.0";
string public constant CALL_PROXY_VERSION = "3.2.0";

// Proxy client - initialize & isFrozen.
// NOLINTNEXTLINE: external-function.
function isFrozen() public pure returns (bool) {
return false;
/*
A single address is expected - the implementation that is call-proxied to.
*/
function numOfSubContracts() internal pure override returns (uint256) {
return 1;
}

/*
There is no initialization needed to be done after the processSubContractAddresses state
thus we return true, to indicate to the ProxySupport that there is no need to get into the
contract state initalization part.
*/
function isInitialized() internal view override returns (bool) {
return true;
}

/*
This function is called by the Proxy upon activating an implementation.
The data passed in to this function contains the implementation address,
and if applicable, an address of an EIC (ExternalInitializerContract) and its data.
The expected data format is as following:
Case I (no EIC):
data.length == 64.
[0 :32] implementation address
[32:64] Zero address.
Case II (EIC):
data length >= 64
[0 :32] implementation address
[32:64] EIC address
[64: ] EIC init data.
Gets the implementation address from the ProxySupport initialize(),
and sets the implementation slot accordingly.
*/
function initialize(bytes calldata data) external notCalledDirectly {
require(data.length >= 64, "INCORRECT_DATA_SIZE");
(address impl, address eic) = abi.decode(data, (address, address));
function processSubContractAddresses(bytes calldata subContractAddresses) internal override {
address impl = abi.decode(subContractAddresses, (address));
require(impl.isContract(), "ADDRESS_NOT_CONTRACT");
setCallProxyImplementation(impl);
if (eic != address(0x0)) {
callExternalInitializer(eic, data[64:]);
} else {
require(data.length == 64, "INVALID_INIT_DATA");
}
}

function callExternalInitializer(address externalInitializerAddr, bytes calldata eicData)
private
{
require(externalInitializerAddr.isContract(), "EIC_NOT_A_CONTRACT");

// NOLINTNEXTLINE: low-level-calls, controlled-delegatecall.
(bool success, bytes memory returndata) = externalInitializerAddr.delegatecall(
abi.encodeWithSelector(this.initialize.selector, eicData)
);
require(success, string(returndata));
require(returndata.length == 0, string(returndata));
/*
In CallProxy a normal init flow has no data,
as the callProxyImplementation was already set by processSubContractAddresses().
*/
function validateInitData(bytes calldata data) internal pure override {
require(data.length == 0, "UNEXPECTED_INIT_DATA");
}

/*
Required by ContractInitializer, Called by ProxySupport.
No processing is needed.
*/
function initializeContractState(bytes calldata) internal override {}

/*
Required by ProxySupport as it inherits Governance.
Not expected to be called.
*/
function getGovernanceInfo() internal view override returns (GovernanceInfoStruct storage) {
revert("NOT_IMPLEMENTED");
}

/*
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: Apache-2.0.
pragma solidity ^0.6.11;
pragma solidity ^0.6.12;

import "./MemoryMap.sol";
import "./MemoryAccessUtils.sol";
Expand Down Expand Up @@ -43,8 +43,8 @@ contract Fri is MemoryMap, MemoryAccessUtils, HornerEvaluator, FriLayer {
function friVerifyLayers(uint256[] memory ctx) internal view virtual {
uint256 friCtx = getPtr(ctx, MM_FRI_CTX);
require(
MAX_SUPPORTED_MAX_FRI_STEP == FRI_MAX_FRI_STEP,
"Incosistent MAX_FRI_STEP between MemoryMap.sol and FriLayer.sol"
MAX_SUPPORTED_FRI_STEP_SIZE == FRI_MAX_STEP_SIZE,
"MAX_STEP_SIZE is inconsistent in MemoryMap.sol and FriLayer.sol"
);
initFriGroups(friCtx);
// emit LogGas("FRI offset precomputation", gasleft());
Expand All @@ -69,10 +69,10 @@ contract Fri is MemoryMap, MemoryAccessUtils, HornerEvaluator, FriLayer {

uint256 friQueue = getPtr(ctx, MM_FRI_QUEUE);

uint256[] memory friSteps = getFriSteps(ctx);
uint256 nFriSteps = friSteps.length;
uint256[] memory friStepSizes = getFriStepSizes(ctx);
uint256 nFriSteps = friStepSizes.length;
while (friStep < nFriSteps) {
uint256 friCosetSize = 2**friSteps[friStep];
uint256 friCosetSize = 2**friStepSizes[friStep];

nLiveQueries = computeNextLayer(
channelPtr,
Expand Down
Loading

0 comments on commit f4ed79b

Please sign in to comment.