Detailed description of the impact of this finding.
In initializeTokenomics function there is no access control as anyone calls and inilize this function.
Proof of Concept
Provide direct links to all referenced code in GitHub. Add screenshots, logs, or any other relevant proof that illustrates the concept.
function initializeTokenomics(
address _olas,
address _treasury,
address _depository,
address _dispenser,
address _ve,
uint256 _epochLen,
address _componentRegistry,
address _agentRegistry,
address _serviceRegistry,
address _donatorBlacklist
) external {
// Check if the contract is already initialized
if (owner != address(0)) {
revert AlreadyInitialized();
}
// Check for at least one zero contract address
if (_olas == address(0) || _treasury == address(0) || _depository == address(0) || _dispenser == address(0) ||
_ve == address(0) || _componentRegistry == address(0) || _agentRegistry == address(0) ||
_serviceRegistry == address(0)) {
revert ZeroAddress();
}
// Initialize storage variables
owner = msg.sender;
_locked = 1;
epsilonRate = 1e17;
veOLASThreshold = 10_000e18;
// Check that the epoch length has at least a practical minimal value
if (uint32(_epochLen) < MIN_EPOCH_LENGTH) {
revert LowerThan(_epochLen, MIN_EPOCH_LENGTH);
}
// Check that the epoch length is not out of defined bounds
if (uint32(_epochLen) > MAX_EPOCH_LENGTH) {
revert Overflow(_epochLen, MAX_EPOCH_LENGTH);
}
// Assign other input variables
olas = _olas;
treasury = _treasury;
depository = _depository;
dispenser = _dispenser;
ve = _ve;
epochLen = uint32(_epochLen);
componentRegistry = _componentRegistry;
agentRegistry = _agentRegistry;
serviceRegistry = _serviceRegistry;
donatorBlacklist = _donatorBlacklist;
// Time launch of the OLAS contract
uint256 _timeLaunch = IOLAS(_olas).timeLaunch();
// Check that the tokenomics contract is initialized no later than one year after the OLAS token is deployed
if (block.timestamp >= (_timeLaunch + ONE_YEAR)) {
revert Overflow(_timeLaunch + ONE_YEAR, block.timestamp);
}
// Seconds left in the deployment year for the zero year inflation schedule
// This value is necessary since it is different from a precise one year time, as the OLAS contract started earlier
uint256 zeroYearSecondsLeft = uint32(_timeLaunch + ONE_YEAR - block.timestamp);
// Calculating initial inflation per second: (mintable OLAS from getInflationForYear(0)) / (seconds left in a year)
// Note that we lose precision here dividing by the number of seconds right away, but to avoid complex calculations
// later we consider it less error-prone and sacrifice at most 6 insignificant digits (or 1e-12) of OLAS per year
uint256 _inflationPerSecond = getInflationForYear(0) / zeroYearSecondsLeft;
inflationPerSecond = uint96(_inflationPerSecond);
timeLaunch = uint32(_timeLaunch);
// The initial epoch start time is the end time of the zero epoch
mapEpochTokenomics[0].epochPoint.endTime = uint32(block.timestamp);
// The epoch counter starts from 1
epochCounter = 1;
TokenomicsPoint storage tp = mapEpochTokenomics[1];
// Setting initial parameters and fractions
devsPerCapital = 1e18;
tp.epochPoint.idf = 1e18;
// Reward fractions
// 0 stands for components and 1 for agents
tp.unitPoints[0].rewardUnitFraction = 83;
tp.unitPoints[1].rewardUnitFraction = 17;
// tp.epochPoint.rewardTreasuryFraction is essentially equal to zero
// We consider a unit of code as n agents or m components.
// Initially we consider 1 unit of code as either 2 agents or 1 component.
// E.g. if we have 2 profitable components and 2 profitable agents, this means there are (2 x 2.0 + 2 x 1.0) / 3 = 2
// units of code.
// We assume that during one epoch the developer can contribute with one piece of code (1 component or 2 agents)
codePerDev = 1e18;
// Top-up fractions
uint256 _maxBondFraction = 50;
tp.epochPoint.maxBondFraction = uint8(_maxBondFraction);
tp.unitPoints[0].topUpUnitFraction = 41;
tp.unitPoints[1].topUpUnitFraction = 9;
// Calculate initial effectiveBond based on the maxBond during the first epoch
// maxBond = inflationPerSecond * epochLen * maxBondFraction / 100
uint256 _maxBond = (_inflationPerSecond * _epochLen * _maxBondFraction) / 100;
maxBond = uint96(_maxBond);
effectiveBond = uint96(_maxBond);
}
Tools Used
Recommended Mitigation Steps
we should define a variable inilized to false earlier and then inilized true in
initializeTokenomics.so that no one can call again.
Lines of code
https://github.com/code-423n4/2024-05-olas/blob/main/tokenomics/contracts/Tokenomics.sol#L409
Vulnerability details
Impact
Detailed description of the impact of this finding. In initializeTokenomics function there is no access control as anyone calls and inilize this function.
Proof of Concept
Provide direct links to all referenced code in GitHub. Add screenshots, logs, or any other relevant proof that illustrates the concept. function initializeTokenomics( address _olas, address _treasury, address _depository, address _dispenser, address _ve, uint256 _epochLen, address _componentRegistry, address _agentRegistry, address _serviceRegistry, address _donatorBlacklist ) external { // Check if the contract is already initialized if (owner != address(0)) { revert AlreadyInitialized(); }
Tools Used
Recommended Mitigation Steps
we should define a variable inilized to false earlier and then inilized true in initializeTokenomics.so that no one can call again.
Assessed type
Access Control