> For the complete documentation index, see [llms.txt](https://calnix.gitbook.io/eth-dev/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://calnix.gitbook.io/eth-dev/compendium/smart-contract-life-cycle.md).

# Smart Contract Life-cycle

How to start, stop, update and destroy a smart contract.

### Insecure Example

```solidity
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.1;

contract StartStopUpdateExample {

    function sendMoney() public payable {

    }

    function withdrawAllMoney(address payable _to) public {
        _to.transfer(address(this).balance);
    }
}
```

![](https://1628544884-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FTgomzlmn9NrxUY0OQ3cD%2Fuploads%2FiTSAq8CKO0NpRB32Sn2d%2Fimage.png?alt=media\&token=34a976ed-e8be-446e-9f0b-1d6234c07767)

* with sendMoney() we can send the SC some ETH
* with withdrawAllMoney(), **anyone** can input their address and withdraw all balances.

### Secure Example

We will secure this SC by ensuring that the person interacting with `withdrawAllMoney` is the same as the one who deployed the Smart Contract.

```solidity
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.1;

contract StartStopUpdateExample {
    
    // set ownership
    address public owner;
    
    constructor(){
        owner = msg.sender;
    }

    function sendMoney() public payable {
    }

    function withdrawAllMoney(address payable _to) public {
        require(owner == msg.sender, "You are not the the owner - cannot withdraw!");
        _to.transfer(address(this).balance);
    }

}
```

* create an address state variable to hold the owner's address.
* use constructor, which will run on deployment, to assign `owner` with the deployer's address.
  * whomever deploys is deemed to be the owner automatically.
* add conditional check, `require` statement, to withdraw function
  * `require` is like `if`, if this condition is true -> proceed. else fails.
  * require checks if the person initiating the withdraw function is indeed owner.
  * if true, balances transferred.
  * If require evaluates to false it will stop the transaction, roll-back any changes made so far and emit the error message as String.

![](https://1628544884-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FTgomzlmn9NrxUY0OQ3cD%2Fuploads%2F8P8AtMtQJqbldpY65g8k%2Fimage.png?alt=media\&token=cb5d4605-edd3-4247-b98a-44b971e47fe0)

{% hint style="info" %}
Note, the msg.sender would be different for the constructor and the withdraw as these are two different interactions with 2 different messages.&#x20;

msg of constructor -> emitted on whomever deployed

msg of withdraw -> emitted on whomever calling withdraw()
{% endhint %}

#### An alternative&#x20;

An alternative way is require(\_to == owner, "...'), this will only allow withdrawals made to the owner/deployer's address.

The above allows the owner to withdraw to an address of choice, different from his deployment wallet.&#x20;

{% hint style="info" %}
Other ownable models:

<https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/Ownable.sol>
{% endhint %}
