mirror of https://github.com/nucypher/nucypher.git
Include Checkpointing library from Aragon's Staking app
parent
eafb57cf17
commit
dd14b55804
|
@ -41,6 +41,7 @@ class SolidityCompiler:
|
|||
|
||||
__compiled_contracts_dir = 'contracts'
|
||||
__zeppelin_library_dir = 'zeppelin'
|
||||
__aragon_library_dir = 'aragon'
|
||||
|
||||
optimization_runs = 200
|
||||
|
||||
|
@ -154,9 +155,11 @@ class SolidityCompiler:
|
|||
|
||||
# Compile with remappings: https://github.com/ethereum/py-solc
|
||||
zeppelin_dir = os.path.join(root_source_dir, self.__zeppelin_library_dir)
|
||||
aragon_dir = os.path.join(root_source_dir, self.__aragon_library_dir)
|
||||
|
||||
remappings = ("contracts={}".format(contracts_dir),
|
||||
"zeppelin={}".format(zeppelin_dir),
|
||||
"aragon={}".format(aragon_dir),
|
||||
)
|
||||
|
||||
self.log.info("Compiling with import remappings {}".format(", ".join(remappings)))
|
||||
|
|
|
@ -0,0 +1,119 @@
|
|||
pragma solidity ^0.4.24;
|
||||
|
||||
|
||||
library Checkpointing {
|
||||
uint256 private constant MAX_UINT192 = uint256(uint192(-1));
|
||||
uint256 private constant MAX_UINT64 = uint256(uint64(-1));
|
||||
|
||||
string private constant ERROR_PAST_CHECKPOINT = "CHECKPOINT_PAST_CHECKPOINT";
|
||||
string private constant ERROR_TIME_TOO_BIG = "CHECKPOINT_TIME_TOO_BIG";
|
||||
string private constant ERROR_VALUE_TOO_BIG = "CHECKPOINT_VALUE_TOO_BIG";
|
||||
|
||||
struct Checkpoint {
|
||||
uint64 time;
|
||||
uint192 value;
|
||||
}
|
||||
|
||||
struct History {
|
||||
Checkpoint[] history;
|
||||
}
|
||||
|
||||
function add(History storage self, uint256 time, uint256 value) internal {
|
||||
require(time <= MAX_UINT64, ERROR_TIME_TOO_BIG);
|
||||
require(value <= MAX_UINT192, ERROR_VALUE_TOO_BIG);
|
||||
|
||||
add192(self, uint64(time), uint192(value));
|
||||
}
|
||||
|
||||
function add64(History storage self, uint64 time, uint256 value) internal {
|
||||
require(value <= MAX_UINT192, ERROR_VALUE_TOO_BIG);
|
||||
|
||||
add192(self, time, uint192(value));
|
||||
}
|
||||
|
||||
function get(History storage self, uint256 time) internal view returns (uint256) {
|
||||
require(time <= MAX_UINT64, ERROR_TIME_TOO_BIG);
|
||||
|
||||
return uint256(get192(self, uint64(time)));
|
||||
}
|
||||
|
||||
function get64(History storage self, uint64 time) internal view returns (uint256) {
|
||||
return uint256(get192(self, time));
|
||||
}
|
||||
|
||||
function lastUpdated(History storage self) internal view returns (uint256) {
|
||||
uint256 length = self.history.length;
|
||||
|
||||
if (length > 0) {
|
||||
return uint256(self.history[length - 1].time);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
function getLatestValue(History storage self) internal view returns (uint256) {
|
||||
uint256 length = self.history.length;
|
||||
if (length > 0) {
|
||||
return uint256(self.history[length - 1].value);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
function add192(History storage self, uint64 time, uint192 value) internal {
|
||||
uint256 length = self.history.length;
|
||||
|
||||
if (length == 0) {
|
||||
self.history.push(Checkpoint(time, value));
|
||||
} else {
|
||||
Checkpoint storage currentCheckpoint = self.history[length - 1];
|
||||
uint64 currentCheckpointTime = currentCheckpoint.time;
|
||||
if (time > currentCheckpointTime) {
|
||||
self.history.push(Checkpoint(time, value));
|
||||
} else if (time == currentCheckpointTime) {
|
||||
currentCheckpoint.value = value;
|
||||
} else { // ensure list ordering
|
||||
revert(ERROR_PAST_CHECKPOINT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function get192(History storage self, uint64 time) internal view returns (uint192) {
|
||||
uint256 length = self.history.length;
|
||||
|
||||
if (length == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint256 lastIndex = length - 1;
|
||||
|
||||
// short-circuit
|
||||
Checkpoint storage lastCheckpoint = self.history[lastIndex];
|
||||
if (time >= lastCheckpoint.time) {
|
||||
return lastCheckpoint.value;
|
||||
}
|
||||
|
||||
if (time < self.history[0].time) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint256 low = 0;
|
||||
uint256 high = lastIndex;
|
||||
|
||||
while (high > low) {
|
||||
uint256 mid = (high + low + 1) / 2; // average, ceil round
|
||||
Checkpoint storage checkpoint = self.history[mid];
|
||||
uint64 midTime = checkpoint.time;
|
||||
|
||||
if (time > midTime) {
|
||||
low = mid;
|
||||
} else if (time < midTime) {
|
||||
high = mid - 1;
|
||||
} else { // time == midTime
|
||||
return checkpoint.value;
|
||||
}
|
||||
}
|
||||
|
||||
return self.history[low].value;
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
pragma solidity ^0.6.5;
|
||||
|
||||
|
||||
import "aragon/staking/Checkpointing.sol";
|
||||
import "contracts/Issuer.sol";
|
||||
import "contracts/lib/Bits.sol";
|
||||
import "zeppelin/math/SafeMath.sol";
|
||||
|
|
4
setup.py
4
setup.py
|
@ -118,7 +118,9 @@ PACKAGE_DATA = ['network/templates/basic_status.j2',
|
|||
'blockchain/eth/sol/source/zeppelin/math/*',
|
||||
'blockchain/eth/sol/source/zeppelin/utils/*',
|
||||
'blockchain/eth/sol/source/zeppelin/ownership/*',
|
||||
'blockchain/eth/sol/source/zeppelin/token/ERC20/*']
|
||||
'blockchain/eth/sol/source/zeppelin/token/ERC20/*',
|
||||
'blockchain/eth/sol/source/aragon/staking/*'
|
||||
]
|
||||
|
||||
setup(name=ABOUT['__title__'],
|
||||
url=ABOUT['__url__'],
|
||||
|
|
Loading…
Reference in New Issue