Solidity
// Add these state variables to your contract
mapping(address => uint256) public syntheticBalance;
uint256 public totalSyntheticSupply;
In the snippet above:
syntheticBalance is a mapping that keeps track of the balance of synthetic assets for each address.totalSyntheticSupply is a variable that keeps track of the total supply of synthetic assets in circulation.Solidity
// Update the mintSyntheticAsset function
function mintSyntheticAsset(uint256 _amount) public {
require(collateral >= _amount, "Insufficient collateral");
syntheticBalance[msg.sender] += _amount;
totalSyntheticSupply += _amount;
collateral -= _amount;
}
In the mintSyntheticAsset function:
require statement checks if there is sufficient collateral to mint the requested amount of synthetic assets.syntheticBalance of the caller (msg.sender) is increased by _amount.totalSyntheticSupply is also increased by _amount.collateral is decreased by _amount as it is used to back the newly minted synthetic assets.Solidity
// Update the redeemSyntheticAsset function
function redeemSyntheticAsset(uint256 _amount) public {
require(syntheticBalance[msg.sender] >= _amount, "Insufficient synthetic balance");
syntheticBalance[msg.sender] -= _amount;
totalSyntheticSupply -= _amount;
collateral += _amount;
}
In the redeemSyntheticAsset function:
require statement checks if the caller has a sufficient balance of synthetic assets to redeem.syntheticBalance of the caller is decreased by _amount.totalSyntheticSupply is decreased by _amount.collateral is increased by _amount as it is released back upon the redemption of synthetic assets.TypeScript
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract SyntheticAsset {
uint256 public underlyingAssetPrice;
uint256 public collateral;
address public owner;
mapping(address => uint256) public syntheticBalance;
uint256 public totalSyntheticSupply;
constructor() {
owner = msg.sender;
}
modifier onlyOwner() {
require(msg.sender == owner, "Not the contract owner");
_;
}
function updatePrice(uint256 _price) public onlyOwner {
underlyingAssetPrice = _price;
}
function depositCollateral(uint256 _amount) public {
collateral += _amount;
}
function withdrawCollateral(uint256 _amount) public {
require(collateral >= _amount, "Insufficient collateral");
collateral -= _amount;
}
function getSyntheticAssetPrice() public view returns (uint256) {
return underlyingAssetPrice;
}
function mintSyntheticAsset(uint256 _amount) public {
require(collateral >= _amount, "Insufficient collateral");
syntheticBalance[msg.sender] += _amount;
totalSyntheticSupply += _amount;
collateral -= _amount;
}
function redeemSyntheticAsset(uint256 _amount) public {
require(syntheticBalance[msg.sender] >= _amount, "Insufficient synthetic balance");
syntheticBalance[msg.sender] -= _amount;
totalSyntheticSupply -= _amount;
collateral += _amount;
}
}

To deploy contracts on the Goerli Testnet, you’ll need Goerli ETH (GoerliETH). While it doesn’t hold any real value, it’s essential for paying gas fees on the testnet.
Metamask: Ensure your Metamask is switched to the Goerli Test Network.
Go to Goerli faucet to request some GoerliETH. Just paste your Goerli Testnet Ethereum address, and you should receive the test ETH shortly.

In Remix, navigate to the Deploy & Run Transactions tab.
For the Environment option, select Injected Provider. This option allows Remix to connect to any network your Metamask is currently set to, which should be Goerli Testnet.
Ensure your contract, OracleIntegratedContract, is selected in the Contract dropdown.
For the Account dropdown, you should see your Goerli Testnet Ethereum address.
Now with the updated functionalities in place, compile and deploy your contract following the steps from Lesson 3.
With the extended contract deployed:
Call mintSyntheticAsset and redeemSyntheticAsset functions with different amounts to mint and redeem synthetic assets respectively.
Observe the changes in syntheticBalance, totalSyntheticSupply, and collateral through the Remix IDE interface.
Engage with the contract and observe how the state variables and the overall contract state evolve with your interactions. This hands-on experience will solidify the concepts and operations of synthetic assets.
As we enrich our contract with essential functionalities, we inch closer to a realistic synthetic asset contract. In the next lesson, we’ll focus on testing this contract to ensure it operates as intended across various scenarios. The practical understanding of synthetic assets continues to deepen as we progress. Stay tuned for more hands-on learning in the upcoming lesson!