Created
August 24, 2017 16:22
-
-
Save retotrinkler/16ca09022c3924ea770eb26953165c22 to your computer and use it in GitHub Desktop.
Oyente Example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// THIS CONTRACT CONTAINS A BUG - DO NOT USE | |
contract Fund { | |
/// Mapping of ether shares of the contract. | |
mapping(address => uint) shares; | |
/// Withdraw your share. | |
function withdraw() { | |
if (msg.sender.call.value(shares[msg.sender])()) | |
shares[msg.sender] = 0; | |
} | |
} | |
contract ICO { | |
mapping(address => uint) magicBeans; | |
uint totalSupply; | |
address company; | |
uint constant fundingGoal = 100000 ether; | |
uint endOfFundingPeriod; | |
modifier checkInvariant() { | |
_; | |
if (this.balance != totalSupply) throw; | |
} | |
function ICO(uint _endOfFundingPeriod ) { | |
company = msg.sender; | |
endOfFundingPeriod = _endOfFundingPeriod; | |
} | |
function() {throw;} | |
function buyMagicBeans() payable checkInvariant() { | |
if (now > endOfFundingPeriod) throw; | |
magicBeans[msg.sender] += msg.value; | |
totalSupply += msg.value; | |
} | |
function refund() checkInvariant() returns(bool) { | |
uint tmpBeans = magicBeans[msg.sender]; | |
magicBeans[msg.sender] = 0; | |
if (now > endOfFundingPeriod | |
&& totalSupply < fundingGoal | |
&& msg.sender.send(tmpBeans)) { | |
totalSupply -= tmpBeans; | |
return true; | |
} | |
else | |
magicBeans[msg.sender] = tmpBeans; | |
} | |
function fundTheProject() returns(bool) { | |
if (now > endOfFundingPeriod + 42 days | |
&& company.send(this.balance)) | |
return true; | |
} | |
} | |
contract KingOfTheEtherThrone { | |
struct Monarch { | |
// Address to which their compensation will be sent. | |
address etherAddress; | |
// A name by which they wish to be known. | |
// NB: Unfortunately "string" seems to expose some bugs in web3. | |
string name; | |
// How much did they pay to become monarch? | |
uint claimPrice; | |
// When did their rule start (based on block.timestamp)? | |
uint coronationTimestamp; | |
} | |
// The wizard is the hidden power behind the throne; they | |
// occupy the throne during gaps in succession and collect fees. | |
address wizardAddress; | |
// Used to ensure only the wizard can do some things. | |
modifier onlywizard { if (msg.sender == wizardAddress) _; } | |
// How much must the first monarch pay? | |
uint constant startingClaimPrice = 100 finney; | |
// The next claimPrice is calculated from the previous claimFee | |
// by multiplying by claimFeeAdjustNum and dividing by claimFeeAdjustDen - | |
// for example, num=3 and den=2 would cause a 50% increase. | |
uint constant claimPriceAdjustNum = 3; | |
uint constant claimPriceAdjustDen = 2; | |
// How much of each claimFee goes to the wizard (expressed as a fraction)? | |
// e.g. num=1 and den=100 would deduct 1% for the wizard, leaving 99% as | |
// the compensation fee for the usurped monarch. | |
uint constant wizardCommissionFractionNum = 1; | |
uint constant wizardCommissionFractionDen = 100; | |
// How much must an agent pay now to become the monarch? | |
uint public currentClaimPrice; | |
// The King (or Queen) of the Ether. | |
Monarch public currentMonarch; | |
// Earliest-first list of previous throne holders. | |
Monarch[] public pastMonarchs; | |
// Create a new throne, with the creator as wizard and first ruler. | |
// Sets up some hopefully sensible defaults. | |
function KingOfTheEtherThrone() { | |
wizardAddress = msg.sender; | |
currentClaimPrice = startingClaimPrice; | |
currentMonarch = Monarch( | |
wizardAddress, | |
"[Vacant]", | |
0, | |
block.timestamp | |
); | |
} | |
function numberOfMonarchs() constant returns (uint n) { | |
return pastMonarchs.length; | |
} | |
// Fired when the throne is claimed. | |
// In theory can be used to help build a front-end. | |
event ThroneClaimed( | |
address usurperEtherAddress, | |
string usurperName, | |
uint newClaimPrice | |
); | |
// Fallback function - simple transactions trigger this. | |
// Assume the message data is their desired name. | |
function() { | |
claimThrone(string(msg.data)); | |
} | |
// Claim the throne for the given name by paying the currentClaimFee. | |
function claimThrone(string name) { | |
uint valuePaid = msg.value; | |
// If they paid too little, reject claim and refund their money. | |
if (valuePaid < currentClaimPrice) { | |
msg.sender.send(valuePaid); | |
return; | |
} | |
// If they paid too much, continue with claim but refund the excess. | |
if (valuePaid > currentClaimPrice) { | |
uint excessPaid = valuePaid - currentClaimPrice; | |
msg.sender.send(excessPaid); | |
valuePaid = valuePaid - excessPaid; | |
} | |
// The claim price payment goes to the current monarch as compensation | |
// (with a commission held back for the wizard). We let the wizard's | |
// payments accumulate to avoid wasting gas sending small fees. | |
uint wizardCommission = (valuePaid * wizardCommissionFractionNum) / wizardCommissionFractionDen; | |
uint compensation = valuePaid - wizardCommission; | |
if (currentMonarch.etherAddress != wizardAddress) { | |
currentMonarch.etherAddress.send(compensation); | |
} else { | |
// When the throne is vacant, the fee accumulates for the wizard. | |
} | |
// Usurp the current monarch, replacing them with the new one. | |
pastMonarchs.push(currentMonarch); | |
currentMonarch = Monarch( | |
msg.sender, | |
name, | |
valuePaid, | |
block.timestamp | |
); | |
// Increase the claim fee for next time. | |
// Stop number of trailing decimals getting silly - we round it a bit. | |
uint rawNewClaimPrice = currentClaimPrice * claimPriceAdjustNum / claimPriceAdjustDen; | |
if (rawNewClaimPrice < 10 finney) { | |
currentClaimPrice = rawNewClaimPrice; | |
} else if (rawNewClaimPrice < 100 finney) { | |
currentClaimPrice = 100 szabo * (rawNewClaimPrice / 100 szabo); | |
} else if (rawNewClaimPrice < 1 ether) { | |
currentClaimPrice = 1 finney * (rawNewClaimPrice / 1 finney); | |
} else if (rawNewClaimPrice < 10 ether) { | |
currentClaimPrice = 10 finney * (rawNewClaimPrice / 10 finney); | |
} else if (rawNewClaimPrice < 100 ether) { | |
currentClaimPrice = 100 finney * (rawNewClaimPrice / 100 finney); | |
} else if (rawNewClaimPrice < 1000 ether) { | |
currentClaimPrice = 1 ether * (rawNewClaimPrice / 1 ether); | |
} else if (rawNewClaimPrice < 10000 ether) { | |
currentClaimPrice = 10 ether * (rawNewClaimPrice / 10 ether); | |
} else { | |
currentClaimPrice = rawNewClaimPrice; | |
} | |
// Hail the new monarch! | |
ThroneClaimed(currentMonarch.etherAddress, currentMonarch.name, currentClaimPrice); | |
} | |
// Used only by the wizard to collect his commission. | |
function sweepCommission(uint amount) onlywizard { | |
wizardAddress.send(amount); | |
} | |
// Used only by the wizard to collect his commission. | |
function transferOwnership(address newOwner) onlywizard { | |
wizardAddress = newOwner; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment