# Investment
What do you think about if stock-exchange server is running on blockchain? Can you buy codegate stock?
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.11;
import "OpenZeppelin/openzeppelin-contracts@4.4.2/contracts/utils/math/SafeMath.sol";
contract Investment {
address private implementation;
address private owner;
address[] public donaters;
using SafeMath for uint;
mapping (address => bool) private _minted;
mapping (bytes32 => uint) private _total_stocks;
mapping (bytes32 => uint) private _reg_stocks;
mapping (address => mapping (bytes32 => uint)) private _stocks;
mapping (address => uint) private _balances;
address lastDonater;
uint fee;
uint denominator;
bool inited;
modifier isInited {
require(inited);
_;
}
function init() public {
require(!inited);
_reg_stocks[keccak256("apple")] = 111;
_total_stocks[keccak256("apple")] = 99999999;
_reg_stocks[keccak256("microsoft")] = 101;
_total_stocks[keccak256("microsoft")] = 99999999;
_reg_stocks[keccak256("intel")] = 97;
_total_stocks[keccak256("intel")] = 99999999;
_reg_stocks[keccak256("amd")] = 74;
_total_stocks[keccak256("amd")] = 99999999;
_reg_stocks[keccak256("codegate")] = 11111111111111111111111111111111111111;
_total_stocks[keccak256("codegate")] = 1;
fee = 5;
denominator = 1e4;
inited = true;
}
function buyStock(string memory _stockName, uint _amountOfStock) public isInited {
bytes32 stockName = keccak256(abi.encodePacked(_stockName));
require(_total_stocks[stockName] > 0 && _amountOfStock > 0);
uint amount = _reg_stocks[stockName].mul(_amountOfStock).mul(denominator + fee).div(denominator);
require(_balances[msg.sender] >= amount);
_balances[msg.sender] -= amount;
_stocks[msg.sender][stockName] += _amountOfStock;
_total_stocks[stockName] -= _amountOfStock;
}
function sellStock(string memory _stockName, uint _amountOfStock) public isInited {
bytes32 stockName = keccak256(abi.encodePacked(_stockName));
require(_amountOfStock > 0);
uint amount = _reg_stocks[stockName].mul(_amountOfStock).mul(denominator).div(denominator + fee);
require(_stocks[msg.sender][stockName] >= _amountOfStock);
_balances[msg.sender] += amount;
_stocks[msg.sender][stockName] -= _amountOfStock;
_total_stocks[stockName] += _amountOfStock;
}
function donateStock(address _to, string memory _stockName, uint _amountOfStock) public isInited {
bytes32 stockName = keccak256(abi.encodePacked(_stockName));
require(_amountOfStock > 0);
require(isUser(msg.sender) && _stocks[msg.sender][stockName] >= _amountOfStock);
_stocks[msg.sender][stockName] -= _amountOfStock;
(bool success, bytes memory result) = msg.sender.call(abi.encodeWithSignature("receiveStock(address,bytes32,uint256)", _to, stockName, _amountOfStock));
require(success);
lastDonater = msg.sender;
donaters.push(lastDonater);
}
function isInvalidDonaters(uint index) internal returns (bool) {
require(donaters.length > index);
if (!isUser(lastDonater)) {
return true;
}
else {
return false;
}
}
function modifyDonater(uint index) public isInited {
require(isInvalidDonaters(index));
donaters[index] = msg.sender;
}
function isUser(address _user) internal returns (bool) {
uint size;
assembly {
size := extcodesize(_user)
}
return size == 0;
}
function mint() public isInited {
require(!_minted[msg.sender]);
_balances[msg.sender] = 300;
_minted[msg.sender] = true;
}
function isSolved() public isInited returns (bool) {
return _total_stocks[keccak256("codegate")] == 0;
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.11;
contract InvestmentProxy {
address implementation;
address owner;
struct log {
bytes12 time;
address sender;
}
log info;
constructor(address _target) {
owner = msg.sender;
implementation = _target;
}
function setImplementation(address _target) public {
require(msg.sender == owner);
implementation = _target;
}
function _delegate(address _target) internal {
assembly {
calldatacopy(0, 0, calldatasize())
let result := delegatecall(gas(), _target, 0, calldatasize(), 0, 0)
returndatacopy(0, 0, returndatasize())
switch result
case 0 {
revert(0, returndatasize())
}
default {
return(0, returndatasize())
}
}
}
function _implementation() internal view returns (address) {
return implementation;
}
function _fallback() internal {
_beforeFallback();
_delegate(_implementation());
}
fallback() external payable {
_fallback();
}
receive() external payable {
_fallback();
}
function _beforeFallback() internal {
info.time = bytes12(uint96(block.timestamp));
info.sender = msg.sender;
}
}
← Thirty Five Tutorial →