Hey @M.K
owner
should be payable if you want to use it as argument of selfdestruct()
.
Cheers,
Dani
import "./Ownable.sol";
contract Destroyable is Ownable {
function close() public onlyOwner {
selfdestruct(msg.sender);
}
}
Hey Daniele, should be payable be written as below ?
contract Destroyable is Ownable {
function close () public onlyOwner {
selfdestruct ( payable owner);
}
}
Or how should i write the code ?
Cheers,
When I created the contract and added the following code, I received an error that owner must be payable. I think this is because if the contract calls selfdestruct it returns funds to the owners address.
pragma solidity 0.7.5;
import './Ownable.sol';
contract Destroyable is Ownable {
function destroy() public onlyOwner {
selfdestruct(owner);
}
}
I thought about changing Ownable.sol, but decided I didnât want every contract that inherited Ownable to consider it payable.
I resolved the the issue within destroyable.sol as follows:
pragma solidity 0.7.5;
import './Ownable.sol';
contract Destroyable is Ownable {
function destroy() public onlyOwner {
address payable owner;
selfdestruct(owner);
}
}
Question:
Iâve looked at the assignment solution code -
address payable receiver = msg.sender;
Isnât this functionally identical to simply âaddress payable ownerâ given that only the owner should be able to use this function?
Unless Iâm missing something the way Iâve done it is simply setting it as an absolute rather than determined by retrieving the sending address (which must be owner),
I thought about there perhaps being an issue with having multiple derived contracts inheriting Ownable, each having a different owner. I cannot work out whether or not this is a problem and if it is functionally how that problem works.
Hey @Shadesvox
Isnât this functionally identical to simply âaddress payable ownerâ given that only the owner should be able to use this function?
Yes is the same thing.
I would use msg.sender
to avoid a variable declaration that costs gas and is not useful here.
function destroy() public onlyOwner {
selfdestruct(msg.sender);
}
Cheers,
Dani
Does this work? If the owner isnât specifically declared as payable in the Ownable.sol contract I think this runs into the same problem.
In all the solutions Iâve seen so far thereâs been some way to specify the sender/owner as payable (since selfdestruct returns funds to msg.sender)
Ok, so I thought more about this and msg.sender
is payable since itâs an address. Is the problem that owner is an object rather than an address? Iâm proper confused here.
Why is this the answer in the solution code?:
address payable receiver = msg.sender;
selfdestruct(receiver);
Hi @Shadesvox
sefldestruct requires a payable address as argument, therefore the function youâve posted works.
You can test it by creating a simple contract on Remix.
Cheers,
Dani
Ok so I simply just used a similar function that was given as an example in the blog we had to read. However when i tried to say selfdestruct(owner) it was throwing an error so i replaced owner with msg.sender. I should probably fix that bug so it works for owner, maybe create a modifier or something.
I also could have put this function in its own separate file and then in the bank contarct inherit from both the ownable contract and the destroy contract using notation like
function Bank is Ownable, Destroyable {......
but i i thought why not just leave it in the own able file to save creating an extra file. It seems just fine here. If i should put it in its own file someone let me know and i will do so if its better practice. Heres my solution code anyway. I added in a bool so the function returns true if executed
contract Ownable
{
//make address public so we have access amount all levels of inheritance
address owner;
modifier onlyOwner
{
require(msg.sender == owner);
_;//means run the function
}
//create a constructor for user input
constructor()
{
owner = msg.sender;
}
//here we can add a destroy contarct function to kill al
//inheriting contracts from this base contratc in the case of
//some bug or internal issuof
function close() public onlyOwner returns(bool)
{
//when the function is called we want to
//destroy the owners address
selfdestruct(msg.sender);
return true;
}
}
contract Destroyable is Ownable{
function close() public onlyOwner{
selfdestruct(owner);
}
}
pragma solidity 0.7.5;
contract Destroyable {
address owner;
modifier onlyOwner {
require(msg.sender == owner);
_;
}
constructor() {
owner = msg.sender;
}
function close() public onlyOwner {
selfdestruct(owner);
}
}
import â./Ownable.solâ;
pragma solidity 0.7.5;
contract Destroyable is Ownable {
function destroy() public onlyOwner {
address payable receiver = msg.sender;
selfdestruct(receiver);
}
}
HI Daniele , what is the below code found in transfer function about ?
govermentInstance.addTransaction(msg.sender, recipient, amount);
where did governmentInstance come from ?
where did .addTransaction come from ?
Please advise
I copied the solution below for your reference
pragma solidity 0.7.5;
import "./Ownable.sol";
import "./Destroyable.sol";
contract Bank is Ownable, Destroyable {
mapping(address => uint) balance;
event depositDone(uint amount, address indexed depositedTo);
function deposit() public payable returns (uint) {
balance[msg.sender] += msg.value;
emit depositDone(msg.value, msg.sender);
return balance[msg.sender];
}
function withdraw(uint amount) public onlyOwner returns (uint){
require(balance[msg.sender] >= amount);
msg.sender.transfer(amount);
return balance[msg.sender];
}
function getBalance() public view returns (uint){
return balance[msg.sender];
}
function transfer(address recipient, uint amount) public {
require(balance[msg.sender] >= amount, "Balance not sufficient");
require(msg.sender != recipient, "Don't transfer money to yourself");
uint previousSenderBalance = balance[msg.sender];
_transfer(msg.sender, recipient, amount);
govermentInstance.addTransaction(msg.sender, recipient, amount);
assert(balance[msg.sender] == previousSenderBalance - amount);
}
function _transfer(address from, address to, uint amount) private {
balance[from] -= amount;
balance[to] += amount;
}
}
Those 2 comes from the interface for the goverment contract, you should be able to learn how to use interfaces from other contracts in further lessons.
Carlos Z
contract Destroyable{
address payable owner;
constructor() {
owner = msg.sender;
}
modifier onlyOwner {
require(msg.sender == owner);
_;
}
function selfDestruction() public onlyOwner {
selfdestruct(owner); //owner will receive all the remaining funds from the contract before selfdestruction
}
}
Hello. Why does Bank inherit from Ownable, and not the other way around? Does it matter which inherits from which?
It does matter, which should be the parent contract? contracts like ownable just have some functions that the bank contract can inherit, so basically depends on which contract should be parent and which are childs (like ownable).
Carlos Z
import "./owner.sol";
contract Destroyable is Ownable {
function kill() public onlyOwner {
selfdestruct(msg.sender);
}
}```
@M.K, If you want you could just create your own function within your bank contract to create a transaction log but i think the reason it was done like this is just to show what can be done with solidiity like here we are getting shown to external contracts and how they can be used in a variety of suituations.
Here are my codes for the Destroyable contract:
pragma solidity 0.8.3;
contract Destroyable {
address owner;
event destroyed(address holder, string message);
constructor(){
owner = msg.sender;
}
modifier onlyOwner {
require(msg.sender == owner);
_;
}
function close() public onlyOwner {
emit destroyed(owner, "Contract destroyed!");
selfdestruct(payable(owner));
}
}
I tried, but without success, finding a way to verify the contract has been destroyed after the close function is executed, so I just make the function to emit an event right before the contract is destroyed to log the action. Donât think itâs an optimal solution. Any suggestions?
Thanks!