Hi @biokillos,
Correct … Now take a look at this post — it explains how you can make an additional adjustment to HelloWorld in terms of the inheritance. I think you’ll find it interesting
Hi @biokillos,
Correct … Now take a look at this post — it explains how you can make an additional adjustment to HelloWorld in terms of the inheritance. I think you’ll find it interesting
Nice solution @chrisdbarnett
Have a look at this post — it explains how and why you can steamline the inheritance code by having HelloWorld just inherit Destroyable. This may also help you to understand why the cleanest inheritance configuration involves Destroyable inheriting Ownable.
Yes, that’s one way to do it. An alternative is to leave the owner state variable definition as non-payable, and convert it to a payable address directly within the selfdestruct function call in Destroyable:
selfdestruct(address(uint160(owner)));
It could be done if:
(i) you pass msg.sender
(instead of owner
) to selfdestruct:
selfdestruct(msg.sender);
If msg.sender
is used directly as a value like this (and not first assigned to a variable) then it is treated as a payable address by default in Solidity, and so it doesn’t need to be converted to a payable address like owner
does;
and
(ii) the selfdestruct function wasn’t restricted to onlyOwner
(which needs to be inherited from Ownable). However, I wouldn’t suggest giving everybody access to this functionality for obvious reasons!
Yes, that means that the contract has been successfully destroyed
import"./Ownable.sol";
pragma solidity 0.5.12;
contract Destroyable is Ownable{
function close() public onlyOwner { //onlyOwner is custom modifier
selfdestruct(msg.sender);
}
}
Destroyable.sol:
import “./Owned.sol”;
pragma solidity 0.5.12;contract Destroyable is Owned{
function close() public onlyOwner {
selfdestruct(address(uint160(owner)));
}
}
HelloWorld.sol:
import “./Owned.sol”;
import “./Destroyable.sol”;
pragma solidity 0.5.12;contract HelloWorld is Owned, Destroyable{
import “./Ownable.sol”;
pragma solidity 0.5.12;
contract Destroyable is Ownable{
function closed() public onlyOwner {
selfdestruct(msg.sender);
}
}
Helloworld
import “./Ownable.sol”;
import “./Destroyablable.sol”;
pragma solidity 0.5.12;
contract HelloWorld is Ownable, Destroyablable{
Made new file Destroyable.sol
import “./ownable.sol”;
contract Destroyable is Ownable {
function close () public onlyOwner {
selfdestruct(msg.sender);
}
}
added to HelloWorld.sol
import “./Destroyable.sol”
and finally changed HelloWorld contract definition
contract HelloWorld is Ownable, Destroyable {
// Hello world file
import ‘./Ownable.sol’;
import ‘./Destroyable.sol’;
pragma solidity 0.5.12;
contract HelloWorld is Ownable, Destroyable{
struct Person {
uint id;
string name;
uint age;
uint height;
bool senior;
}......
…
}
// Ownable file
pragma solidity 0.5.12;
contract Ownable{
address payable public owner;
modifier onlyOwner(){
require(msg.sender == owner);
_;
}
constructor () public {
owner = msg.sender;
}
}
// Destroyable file
import ‘./Ownable.sol’;
pragma solidity 0.5.12;
contract Destroyable is Ownable {
function close() public onlyOwner {
selfdestruct(owner);
}
}
for the Destroyable contract:
import "./Ownable.sol";
pragma solidity 0.5.12;
contract Destroyable is Ownable {
function close() public onlyOwner { //onlyOwner is custom modifier
selfdestruct(msg.sender); // `owner` is the owners address
}
}
for the helloWorld contract:
import "./Ownable.sol";
import "./Destroyable.sol";
pragma solidity 0.5.12;
contract HelloWorld is Ownable, Destroyable {
Destroyable contract:
pragma solidity 0.5.12;
import './Ownable.sol';
contract Destroyable is Ownable {
function destroyContract() public onlyOwner {
selfdestruct(owner);
}
}
HelloWorld contract changes:
import './Destroyable.sol';
contract HelloWorld is Ownable, Destroyable {
Ownable contract modified woner address to payable:
address payable public owner;
From Destroyable Contract
import "./Ownable.sol";
pragma solidity 0.5.12;
contract Destroyable is Ownable { // we inherit the code needed from contract Ownable
function destroyContract() public onlyOwner { // The modifier we set up in contract Ownable
selfdestruct(msg.sender); // destruction can be achieved only by the owner
}
}
From HelloPerson Contract
import "./Ownable.sol";
import "./Destroyable.sol"; // allow us to destroy HelloPerson contract
pragma solidity 0.5.12;
contract HelloPerson is Ownable, Destroyable {
“Ownable.sol”:
pragma solidity 0.5.12;
contract Ownable {
// STATE VARIABLES
address public owner;
modifier onlyOwner() {
require (msg.sender == owner);
_;
}
// FUNCTIONS
// Only runs once throughout the duration of the contract
constructor () public {
owner = msg.sender;
}
}
“Destroyable.sol”:
import “./Ownable.sol”;
pragma solidity 0.5.12;
contract Destroyable is Ownable{
function deleteContract() public onlyOwner {
selfdestruct(address(uint160(owner)));
}
}
“HelloWorld.sol”:
function closeContract () public onlyOwner {
deleteContract ();
}
Here is the contract for the self destruct contract.
pragma solidity 0.5.12;
contract Destroyable {
address payable private owner;
constructor() public {
owner = msg.sender;
}
function close() public {
selfdestruct(owner);
}
}
I was not sure how to get the our contract to point to the Destroyable child contract, so I just added another import command. Seems to compile fine.
import "./Ownable.sol";
import "./Destroyable.sol";
pragma solidity 0.5.12;
contract HeyYoungWorld is Ownable, Destroyable {
struct Person {
string name;
uint age;
uint height;
bool senior;
}
event personCreated(string name, bool senior);
event personDeleted(string name, bool senior, address deletedBy);
uint public balance;
/* modifier costs(uint cost){
require(msg.value >= cost);
_;
}*/
// Runs when at the time the contracy is created
mapping(address => Person) private people;
// An Array for saving addresses
address[]private creators;
function createPerson(string memory name, uint age, uint height) public {
require(age < 150, "Age needs to be less than 150.");
// balance = balance + msg.value;
//balance += msg.value;
// check if payment is >= 1 ET
// This creates a person
Person memory newPerson;
newPerson.name = name;
newPerson.age = age;
newPerson.height = height;
if(age >= 65){
newPerson.senior = true;
}
else{
newPerson.senior = false;
}
insertPerson(newPerson);
// Adds an entry into the Array
creators.push(msg.sender);
//people[msg.sender] == person
assert(
keccak256(
abi.encodePacked(
people[msg.sender].name,
people[msg.sender].age,
people[msg.sender].height,
people[msg.sender].senior
)
)
==
keccak256(
abi.encodePacked(
newPerson.name,
newPerson.age,
newPerson.height,
newPerson.senior
)
)
);
emit personCreated(newPerson.name, newPerson.senior);
}
function insertPerson(Person memory newPerson) private{
address creator = msg.sender;
people[creator] = newPerson;
}
function getPerson() public view returns(string memory name, uint age, uint height, bool senior){
address creator = msg.sender;
return (people[creator].name, people[creator].age, people[creator].height, people[creator].senior);
}
function deletePerson(address creator) public onlyOwner {
string memory name = people[creator].name;
bool senior = people[creator].senior;
delete people[creator];
assert(people[creator].age == 0);
emit personDeleted(name, senior, msg.sender);
}
function getCreator(uint index) public view onlyOwner returns(address) {
return creators[index];
}
}
HelloWorld.sol would have its contract extended like this:
contract HelloWorld is Ownable, Destroyable{
}
and the new Destroyable contract would contain the following code:
pragma solidity 0.5.12;
contract Destroy is Ownable {
function closeContract() public onlyOwner {
selfdestruct(msg.sender);
}
}
import “./Ownable.sol”;
pragma solidity 0.5.12;
contract Destroyable is Ownable {
function destroyContract() public onlyOwner {
selfdestruct(address(uint160(owner)));
}
}
Hi @keithra1948,
Well done for finding a way round not knowing how to get Destroyable to inherit Ownable. It does compile, but the problem is that the selfdestruct function is not restricted to onlyOwner, so anyone can call it. The other issue is that you also now have duplicated code in Ownable and Destroyable.
To solve these issues, and get Destroyable to inherit Ownable, you need to modify Destroyable as follows:
// Add at the top to import Ownable.sol
import "./Ownable.sol";
// Inherit contract Ownable
contract Destroyable is Ownable {...}
You can now remove the owner variable and the constructor from Destroyable, and only include them in Ownable, together with the onlyOwner modifier. You need to keep the owner variable payable, so that when it is inherited by Destroyable it can still be used in the selfdestruct function to transfer the remaining contract balance to the owner. However, you will have to now change its visibility from private to either internal or public, otherwise it won’t be available to Destroyable.
As Destroyable now inherits Ownable, you can also remove from HelloWorld the code which explicity inherits Ownable. This is because HelloWorld also inherits from Destroyable, and so now indirectly inherits Ownable via Destroyable.
Hi @Jun_0113,
If you pass owner
as the argument to selfdestruct() instead of msg.sender
, then you also need to either make an additional modification to contract Ownable, or add some additional code to contract Destroyable.
Do you know what this is, and why?
Hi @ThisIsNotStefan,
Good… but don’t forget to import the files with the inherited contracts.
Also, …
… should be contract Destroyable
, as contract Destroy
doesn’t exist