Contract Source Code:
File 1 of 1 : Units
pragma solidity ^0.4.25;
/**
*
* World War Goo - Competitive Idle Game
*
* https://ethergoo.io
*
*/
contract Units {
GooToken constant goo = GooToken(0xdf0960778c6e6597f197ed9a25f12f5d971da86c);
Army army = Army(0x0);
Clans clans = Clans(0x0);
Factories constant factories = Factories(0xc81068cd335889736fc485592e4d73a82403d44b);
mapping(address => mapping(uint256 => UnitsOwned)) public unitsOwned;
mapping(address => mapping(uint256 => UnitExperience)) public unitExp;
mapping(address => mapping(uint256 => uint256)) private unitMaxCap;
mapping(address => mapping(uint256 => UnitUpgrades)) private unitUpgrades;
mapping(address => mapping(uint256 => UpgradesOwned)) public upgradesOwned; // For each unitId, which upgrades owned (3 columns of uint64)
mapping(uint256 => Unit) public unitList;
mapping(uint256 => Upgrade) public upgradeList;
mapping(address => bool) operator;
address owner;
constructor() public {
owner = msg.sender;
}
struct UnitsOwned {
uint80 units;
uint8 factoryBuiltFlag; // Incase user sells units, we still want to keep factory
}
struct UnitExperience {
uint224 experience;
uint32 level;
}
struct UnitUpgrades {
uint32 prodIncrease;
uint32 prodMultiplier;
uint32 attackIncrease;
uint32 attackMultiplier;
uint32 defenseIncrease;
uint32 defenseMultiplier;
uint32 lootingIncrease;
uint32 lootingMultiplier;
}
struct UpgradesOwned {
uint64 column0;
uint64 column1;
uint64 column2;
}
// Unit & Upgrade data:
struct Unit {
uint256 unitId;
uint224 gooCost;
uint256 baseProduction;
uint80 attack;
uint80 defense;
uint80 looting;
}
struct Upgrade {
uint256 upgradeId;
uint224 gooCost;
uint256 unitId;
uint256 column; // Columns of upgrades (1st & 2nd are unit specific, then 3rd is capacity)
uint256 prerequisiteUpgrade;
uint256 unitMaxCapacityGain;
uint32 prodIncrease;
uint32 prodMultiplier;
uint32 attackIncrease;
uint32 attackMultiplier;
uint32 defenseIncrease;
uint32 defenseMultiplier;
uint32 lootingIncrease;
uint32 lootingMultiplier;
}
function setArmy(address armyContract) external {
require(msg.sender == owner);
army = Army(armyContract);
}
function setClans(address clansContract) external {
require(msg.sender == owner);
clans = Clans(clansContract);
}
function setOperator(address gameContract, bool isOperator) external {
require(msg.sender == owner);
operator[gameContract] = isOperator;
}
function mintUnitExternal(uint256 unit, uint80 amount, address player, uint8 chosenPosition) external {
require(operator[msg.sender]);
mintUnit(unit, amount, player, chosenPosition);
}
function mintUnit(uint256 unit, uint80 amount, address player, uint8 chosenPosition) internal {
UnitsOwned storage existingUnits = unitsOwned[player][unit];
if (existingUnits.factoryBuiltFlag == 0) {
// Edge case to create factory for player (on empty tile) where it is their first unit
uint256[] memory existingFactories = factories.getFactories(player);
uint256 length = existingFactories.length;
// Provided position is not valid so find valid factory position
if (chosenPosition >= factories.MAX_SIZE() || (chosenPosition < length && existingFactories[chosenPosition] > 0)) {
chosenPosition = 0;
while (chosenPosition < length && existingFactories[chosenPosition] > 0) {
chosenPosition++;
}
}
factories.addFactory(player, chosenPosition, unit);
unitsOwned[player][unit] = UnitsOwned(amount, 1); // 1 = Flag to say factory exists
} else {
existingUnits.units += amount;
}
(uint80 attackStats, uint80 defenseStats, uint80 lootingStats) = getUnitsCurrentBattleStats(player, unit);
if (attackStats > 0 || defenseStats > 0 || lootingStats > 0) {
army.increasePlayersArmyPowerTrio(player, attackStats * amount, defenseStats * amount, lootingStats * amount);
} else {
uint256 prodIncrease = getUnitsCurrentProduction(player, unit) * amount;
goo.increasePlayersGooProduction(player, prodIncrease / 100);
}
}
function deleteUnitExternal(uint80 amount, uint256 unit, address player) external {
require(operator[msg.sender]);
deleteUnit(amount, unit, player);
}
function deleteUnit(uint80 amount, uint256 unit, address player) internal {
(uint80 attackStats, uint80 defenseStats, uint80 lootingStats) = getUnitsCurrentBattleStats(player, unit);
if (attackStats > 0 || defenseStats > 0 || lootingStats > 0) {
army.decreasePlayersArmyPowerTrio(player, attackStats * amount, defenseStats * amount, lootingStats * amount);
} else {
uint256 prodDecrease = getUnitsCurrentProduction(player, unit) * amount;
goo.decreasePlayersGooProduction(player, prodDecrease / 100);
}
unitsOwned[player][unit].units -= amount;
}
function getUnitsCurrentBattleStats(address player, uint256 unitId) internal view returns (uint80 attack, uint80 defense, uint80 looting) {
Unit memory unit = unitList[unitId];
UnitUpgrades memory existingUpgrades = unitUpgrades[player][unitId];
attack = (unit.attack + existingUpgrades.attackIncrease) * (100 + existingUpgrades.attackMultiplier);
defense = (unit.defense + existingUpgrades.defenseIncrease) * (100 + existingUpgrades.defenseMultiplier);
looting = (unit.looting + existingUpgrades.lootingIncrease) * (100 + existingUpgrades.lootingMultiplier);
}
function getUnitsCurrentProduction(address player, uint256 unitId) public view returns (uint256) {
UnitUpgrades memory existingUpgrades = unitUpgrades[player][unitId];
return (unitList[unitId].baseProduction + existingUpgrades.prodIncrease) * (100 + existingUpgrades.prodMultiplier);
}
function buyUnit(uint256 unitId, uint80 amount, uint8 position) external {
uint224 gooCost = SafeMath224.mul(unitList[unitId].gooCost, amount);
require(gooCost > 0); // Valid unit
uint80 newTotal = unitsOwned[msg.sender][unitId].units + amount;
if (newTotal > 99) {
require(newTotal < 99 + unitMaxCap[msg.sender][unitId]);
}
// Clan discount
uint224 unitDiscount = clans.getPlayersClanUpgrade(msg.sender, 1); // class 1 = unit discount
uint224 reducedGooCost = gooCost - ((gooCost * unitDiscount) / 100);
uint224 seventyFivePercentRefund = (gooCost * 3) / 4;
// Update players goo
goo.updatePlayersGooFromPurchase(msg.sender, reducedGooCost);
goo.mintGoo(seventyFivePercentRefund, this); // 75% refund is stored (in this contract) for when player sells unit
army.depositSpentGoo(reducedGooCost - seventyFivePercentRefund); // Upto 25% Goo spent goes to divs (Remaining is discount + 75% player gets back when selling unit)
mintUnit(unitId, amount, msg.sender, position);
}
function sellUnit(uint256 unitId, uint80 amount) external {
require(unitsOwned[msg.sender][unitId].units >= amount && amount > 0);
uint224 gooCost = unitList[unitId].gooCost;
require(gooCost > 0);
goo.updatePlayersGoo(msg.sender);
deleteUnit(amount, unitId, msg.sender);
goo.transfer(msg.sender, (gooCost * amount * 3) / 4); // Refund 75%
}
function grantArmyExp(address player, uint256 unitId, uint224 amount) external returns(bool) {
require(operator[msg.sender]);
UnitExperience memory existingExp = unitExp[player][unitId];
uint224 expRequirement = (existingExp.level + 1) * 80; // Lvl 1: 80; Lvl 2: 160, Lvl 3: 240 (480 in total) etc.
if (existingExp.experience + amount >= expRequirement) {
existingExp.experience = (existingExp.experience + amount) - expRequirement;
existingExp.level++;
unitExp[player][unitId] = existingExp;
// Grant buff to unit (5% additive multiplier)
UnitUpgrades memory existingUpgrades = unitUpgrades[player][unitId];
existingUpgrades.attackMultiplier += 5;
existingUpgrades.defenseMultiplier += 5;
existingUpgrades.lootingMultiplier += 5;
unitUpgrades[player][unitId] = existingUpgrades;
// Increase player's army power
uint80 multiplierGain = unitsOwned[player][unitId].units * 5;
Unit memory unit = unitList[unitId];
uint80 attackGain = multiplierGain * (unit.attack + existingUpgrades.attackIncrease);
uint80 defenseGain = multiplierGain * (unit.defense + existingUpgrades.defenseIncrease);
uint80 lootingGain = multiplierGain * (unit.looting + existingUpgrades.lootingIncrease);
army.increasePlayersArmyPowerTrio(player, attackGain, defenseGain, lootingGain);
return true;
} else {
unitExp[player][unitId].experience += amount;
return false;
}
}
function increaseUnitCapacity(address player, uint256 upgradeGain, uint256 unitId) external {
require(operator[msg.sender]);
unitMaxCap[player][unitId] += upgradeGain;
}
function decreaseUnitCapacity(address player, uint256 upgradeGain, uint256 unitId) external {
require(operator[msg.sender]);
unitMaxCap[player][unitId] -= upgradeGain;
}
function increaseUpgradesExternal(address player, uint256 unitId, uint32 prodIncrease, uint32 prodMultiplier, uint32 attackIncrease, uint32 attackMultiplier, uint32 defenseIncrease, uint32 defenseMultiplier, uint32 lootingIncrease, uint32 lootingMultiplier) external {
require(operator[msg.sender]);
Upgrade memory upgrade = Upgrade(0,0,0,0,0,0, prodIncrease, prodMultiplier, attackIncrease, attackMultiplier, defenseIncrease, defenseMultiplier, lootingIncrease, lootingMultiplier);
increaseUpgrades(player, upgrade, unitId);
}
function increaseUpgrades(address player, Upgrade upgrade, uint256 unitId) internal {
uint80 units = unitsOwned[player][unitId].units;
UnitUpgrades memory existingUpgrades = unitUpgrades[player][unitId];
Unit memory unit = unitList[unitId];
if (unit.baseProduction > 0) {
// Increase goo production
uint256 prodGain = units * upgrade.prodMultiplier * (unit.baseProduction + existingUpgrades.prodIncrease); // Multiplier gains
prodGain += units * upgrade.prodIncrease * (100 + existingUpgrades.prodMultiplier); // Base prod gains
goo.updatePlayersGoo(player);
goo.increasePlayersGooProduction(player, prodGain / 100);
} else {
// Increase army power
uint80 attackGain = units * upgrade.attackMultiplier * (unit.attack + existingUpgrades.attackIncrease); // Multiplier gains
uint80 defenseGain = units * upgrade.defenseMultiplier * (unit.defense + existingUpgrades.defenseIncrease); // Multiplier gains
uint80 lootingGain = units * upgrade.lootingMultiplier * (unit.looting + existingUpgrades.lootingIncrease); // Multiplier gains
attackGain += units * upgrade.attackIncrease * (100 + existingUpgrades.attackMultiplier); // + Base gains
defenseGain += units * upgrade.defenseIncrease * (100 + existingUpgrades.defenseMultiplier); // + Base gains
lootingGain += units * upgrade.lootingIncrease * (100 + existingUpgrades.lootingMultiplier); // + Base gains
army.increasePlayersArmyPowerTrio(player, attackGain, defenseGain, lootingGain);
}
existingUpgrades.prodIncrease += upgrade.prodIncrease;
existingUpgrades.prodMultiplier += upgrade.prodMultiplier;
existingUpgrades.attackIncrease += upgrade.attackIncrease;
existingUpgrades.attackMultiplier += upgrade.attackMultiplier;
existingUpgrades.defenseIncrease += upgrade.defenseIncrease;
existingUpgrades.defenseMultiplier += upgrade.defenseMultiplier;
existingUpgrades.lootingIncrease += upgrade.lootingIncrease;
existingUpgrades.lootingMultiplier += upgrade.lootingMultiplier;
unitUpgrades[player][unitId] = existingUpgrades;
}
function decreaseUpgradesExternal(address player, uint256 unitId, uint32 prodIncrease, uint32 prodMultiplier, uint32 attackIncrease, uint32 attackMultiplier, uint32 defenseIncrease, uint32 defenseMultiplier, uint32 lootingIncrease, uint32 lootingMultiplier) external {
require(operator[msg.sender]);
Upgrade memory upgrade = Upgrade(0,0,0,0,0,0, prodIncrease, prodMultiplier, attackIncrease, attackMultiplier, defenseIncrease, defenseMultiplier, lootingIncrease, lootingMultiplier);
decreaseUpgrades(player, upgrade, unitId);
}
function decreaseUpgrades(address player, Upgrade upgrade, uint256 unitId) internal {
uint80 units = unitsOwned[player][unitId].units;
UnitUpgrades memory existingUpgrades = unitUpgrades[player][unitId];
Unit memory unit = unitList[unitId];
if (unit.baseProduction > 0) {
// Decrease goo production
uint256 prodLoss = units * upgrade.prodMultiplier * (unit.baseProduction + existingUpgrades.prodIncrease); // Multiplier losses
prodLoss += units * upgrade.prodIncrease * (100 + existingUpgrades.prodMultiplier); // Base prod losses
goo.updatePlayersGoo(player);
goo.decreasePlayersGooProduction(player, prodLoss / 100);
} else {
// Decrease army power
uint80 attackLoss = units * upgrade.attackMultiplier * (unit.attack + existingUpgrades.attackIncrease); // Multiplier losses
uint80 defenseLoss = units * upgrade.defenseMultiplier * (unit.defense + existingUpgrades.defenseIncrease); // Multiplier losses
uint80 lootingLoss = units * upgrade.lootingMultiplier * (unit.looting + existingUpgrades.lootingIncrease); // Multiplier losses
attackLoss += units * upgrade.attackIncrease * (100 + existingUpgrades.attackMultiplier); // + Base losses
defenseLoss += units * upgrade.defenseIncrease * (100 + existingUpgrades.defenseMultiplier); // + Base losses
lootingLoss += units * upgrade.lootingIncrease * (100 + existingUpgrades.lootingMultiplier); // + Base losses
army.decreasePlayersArmyPowerTrio(player, attackLoss, defenseLoss, lootingLoss);
}
existingUpgrades.prodIncrease -= upgrade.prodIncrease;
existingUpgrades.prodMultiplier -= upgrade.prodMultiplier;
existingUpgrades.attackIncrease -= upgrade.attackIncrease;
existingUpgrades.attackMultiplier -= upgrade.attackMultiplier;
existingUpgrades.defenseIncrease -= upgrade.defenseIncrease;
existingUpgrades.defenseMultiplier -= upgrade.defenseMultiplier;
existingUpgrades.lootingIncrease -= upgrade.lootingIncrease;
existingUpgrades.lootingMultiplier -= upgrade.lootingMultiplier;
unitUpgrades[player][unitId] = existingUpgrades;
}
function swapUpgradesExternal(address player, uint256 unitId, uint32[8] upgradeGains, uint32[8] upgradeLosses) external {
require(operator[msg.sender]);
UnitUpgrades memory existingUpgrades = unitUpgrades[player][unitId];
Unit memory unit = unitList[unitId];
if (unit.baseProduction > 0) {
// Change goo production
gooProductionChange(player, unitId, existingUpgrades, unit.baseProduction, upgradeGains, upgradeLosses);
} else {
// Change army power
armyPowerChange(player, existingUpgrades, unit, upgradeGains, upgradeLosses);
}
}
function armyPowerChange(address player, UnitUpgrades existingUpgrades, Unit unit, uint32[8] upgradeGains, uint32[8] upgradeLosses) internal {
int256 existingAttack = int256((unit.attack + existingUpgrades.attackIncrease) * (100 + existingUpgrades.attackMultiplier));
int256 existingDefense = int256((unit.defense + existingUpgrades.defenseIncrease) * (100 + existingUpgrades.defenseMultiplier));
int256 existingLooting = int256((unit.looting + existingUpgrades.lootingIncrease) * (100 + existingUpgrades.lootingMultiplier));
existingUpgrades.attackIncrease = uint32(int(existingUpgrades.attackIncrease) + (int32(upgradeGains[2]) - int32(upgradeLosses[2])));
existingUpgrades.attackMultiplier = uint32(int(existingUpgrades.attackMultiplier) + (int32(upgradeGains[3]) - int32(upgradeLosses[3])));
existingUpgrades.defenseIncrease = uint32(int(existingUpgrades.defenseIncrease) + (int32(upgradeGains[4]) - int32(upgradeLosses[4])));
existingUpgrades.defenseMultiplier = uint32(int(existingUpgrades.defenseMultiplier) + (int32(upgradeGains[5]) - int32(upgradeLosses[5])));
existingUpgrades.lootingIncrease = uint32(int(existingUpgrades.lootingIncrease) + (int32(upgradeGains[6]) - int32(upgradeLosses[6])));
existingUpgrades.lootingMultiplier = uint32(int(existingUpgrades.lootingMultiplier) + (int32(upgradeGains[7]) - int32(upgradeLosses[7])));
int256 attackChange = ((int256(unit.attack) + existingUpgrades.attackIncrease) * (100 + existingUpgrades.attackMultiplier)) - existingAttack;
int256 defenseChange = ((int256(unit.defense) + existingUpgrades.defenseIncrease) * (100 + existingUpgrades.defenseMultiplier)) - existingDefense;
int256 lootingChange = ((int256(unit.looting) + existingUpgrades.lootingIncrease) * (100 + existingUpgrades.lootingMultiplier)) - existingLooting;
uint256 unitId = unit.unitId;
int256 units = int256(unitsOwned[player][unitId].units);
army.changePlayersArmyPowerTrio(player, units * attackChange, units * defenseChange, units * lootingChange);
unitUpgrades[player][unitId] = existingUpgrades;
}
function gooProductionChange(address player, uint256 unitId, UnitUpgrades existingUpgrades, uint256 baseProduction, uint32[8] upgradeGains, uint32[8] upgradeLosses) internal {
goo.updatePlayersGoo(player);
int256 existingProd = int256((baseProduction + existingUpgrades.prodIncrease) * (100 + existingUpgrades.prodMultiplier));
existingUpgrades.prodIncrease = uint32(int(existingUpgrades.prodIncrease) + (int32(upgradeGains[0]) - int32(upgradeLosses[0])));
existingUpgrades.prodMultiplier = uint32(int(existingUpgrades.prodMultiplier) + (int32(upgradeGains[1]) - int32(upgradeLosses[1])));
int256 prodChange = ((int256(baseProduction) + existingUpgrades.prodIncrease) * (100 + existingUpgrades.prodMultiplier)) - existingProd;
if (prodChange > 0) {
goo.increasePlayersGooProduction(player, (unitsOwned[player][unitId].units * uint256(prodChange)) / 100);
} else {
goo.decreasePlayersGooProduction(player, (unitsOwned[player][unitId].units * uint256(-prodChange)) / 100);
}
unitUpgrades[player][unitId] = existingUpgrades;
}
function addUnit(uint256 id, uint224 baseGooCost, uint256 baseGooProduction, uint80 baseAttack, uint80 baseDefense, uint80 baseLooting) external {
require(operator[msg.sender]);
unitList[id] = Unit(id, baseGooCost, baseGooProduction, baseAttack, baseDefense, baseLooting);
}
function addUpgrade(uint256 id, uint224 gooCost, uint256 unit, uint256 column, uint256 prereq, uint256 unitMaxCapacityGain, uint32[8] upgradeGains) external {
require(operator[msg.sender]);
upgradeList[id] = Upgrade(id, gooCost, unit, column, prereq, unitMaxCapacityGain, upgradeGains[0], upgradeGains[1], upgradeGains[2], upgradeGains[3], upgradeGains[4], upgradeGains[5], upgradeGains[6], upgradeGains[7]);
}
function buyUpgrade(uint64 upgradeId) external {
Upgrade memory upgrade = upgradeList[upgradeId];
uint256 unitId = upgrade.unitId;
UpgradesOwned memory ownedUpgrades = upgradesOwned[msg.sender][unitId];
uint64 latestUpgradeOwnedForColumn;
if (upgrade.column == 0) {
latestUpgradeOwnedForColumn = ownedUpgrades.column0;
ownedUpgrades.column0 = upgradeId; // Update upgradesOwned
} else if (upgrade.column == 1) {
latestUpgradeOwnedForColumn = ownedUpgrades.column1;
ownedUpgrades.column1 = upgradeId; // Update upgradesOwned
} else if (upgrade.column == 2) {
latestUpgradeOwnedForColumn = ownedUpgrades.column2;
ownedUpgrades.column2 = upgradeId; // Update upgradesOwned
}
upgradesOwned[msg.sender][unitId] = ownedUpgrades;
require(unitId > 0); // Valid upgrade
require(latestUpgradeOwnedForColumn < upgradeId); // Haven't already purchased
require(latestUpgradeOwnedForColumn >= upgrade.prerequisiteUpgrade); // Own prequisite
// Clan discount
uint224 upgradeDiscount = clans.getPlayersClanUpgrade(msg.sender, 0); // class 0 = upgrade discount
uint224 reducedUpgradeCost = upgrade.gooCost - ((upgrade.gooCost * upgradeDiscount) / 100);
// Update players goo
goo.updatePlayersGooFromPurchase(msg.sender, reducedUpgradeCost);
army.depositSpentGoo(reducedUpgradeCost); // Transfer to goo bankroll
// Update stats for upgrade
if (upgrade.column == 2) {
unitMaxCap[msg.sender][unitId] += upgrade.unitMaxCapacityGain;
} else if (upgrade.column == 1) {
increaseUpgrades(msg.sender, upgrade, unitId);
} else if (upgrade.column == 0) {
increaseUpgrades(msg.sender, upgrade, unitId);
}
}
}
contract GooToken {
function transfer(address to, uint256 tokens) external returns (bool);
function increasePlayersGooProduction(address player, uint256 increase) external;
function decreasePlayersGooProduction(address player, uint256 decrease) external;
function updatePlayersGooFromPurchase(address player, uint224 purchaseCost) external;
function updatePlayersGoo(address player) external;
function mintGoo(uint224 amount, address player) external;
}
contract Army {
function depositSpentGoo(uint224 gooSpent) external;
function increasePlayersArmyPowerTrio(address player, uint80 attackGain, uint80 defenseGain, uint80 lootingGain) public;
function decreasePlayersArmyPowerTrio(address player, uint80 attackLoss, uint80 defenseLoss, uint80 lootingLoss) public;
function changePlayersArmyPowerTrio(address player, int attackChange, int defenseChange, int lootingChange) public;
}
contract Clans {
mapping(uint256 => uint256) public clanTotalArmyPower;
function totalSupply() external view returns (uint256);
function depositGoo(uint256 amount, uint256 clanId) external;
function getPlayerFees(address player) external view returns (uint224 clansFee, uint224 leadersFee, address leader, uint224 referalsFee, address referer);
function getPlayersClanUpgrade(address player, uint256 upgradeClass) external view returns (uint224 upgradeGain);
function mintGoo(address player, uint256 amount) external;
function increaseClanPower(address player, uint256 amount) external;
function decreaseClanPower(address player, uint256 amount) external;
}
contract Factories {
uint256 public constant MAX_SIZE = 40;
function getFactories(address player) external returns (uint256[]);
function addFactory(address player, uint8 position, uint256 unitId) external;
}
library SafeMath {
/**
* @dev Multiplies two numbers, throws on overflow.
*/
function mul(uint224 a, uint224 b) internal pure returns (uint224) {
if (a == 0) {
return 0;
}
uint224 c = a * b;
assert(c / a == b);
return c;
}
/**
* @dev Integer division of two numbers, truncating the quotient.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
// assert(b > 0); // Solidity automatically throws when dividing by 0
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
/**
* @dev Substracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend).
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
assert(b <= a);
return a - b;
}
/**
* @dev Adds two numbers, throws on overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
assert(c >= a);
return c;
}
}
library SafeMath224 {
/**
* @dev Multiplies two numbers, throws on overflow.
*/
function mul(uint224 a, uint224 b) internal pure returns (uint224) {
if (a == 0) {
return 0;
}
uint224 c = a * b;
assert(c / a == b);
return c;
}
/**
* @dev Integer division of two numbers, truncating the quotient.
*/
function div(uint224 a, uint224 b) internal pure returns (uint224) {
// assert(b > 0); // Solidity automatically throws when dividing by 0
uint224 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
/**
* @dev Substracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend).
*/
function sub(uint224 a, uint224 b) internal pure returns (uint224) {
assert(b <= a);
return a - b;
}
/**
* @dev Adds two numbers, throws on overflow.
*/
function add(uint224 a, uint224 b) internal pure returns (uint224) {
uint224 c = a + b;
assert(c >= a);
return c;
}
}