Skip to content

Instantly share code, notes, and snippets.

@Turupawn
Last active August 11, 2024 12:58
Show Gist options
  • Save Turupawn/382567383afbde8ddae3954d3d00dc3c to your computer and use it in GitHub Desktop.
Save Turupawn/382567383afbde8ddae3954d3d00dc3c to your computer and use it in GitHub Desktop.
DeFi Hackathon
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
library DataTypes {
struct ReserveConfigurationMap {
uint256 data;
}
struct ReserveData {
ReserveConfigurationMap configuration;
uint128 liquidityIndex;
uint128 currentLiquidityRate;
uint128 variableBorrowIndex;
uint128 currentVariableBorrowRate;
uint128 currentStableBorrowRate;
uint40 lastUpdateTimestamp;
uint16 id;
address aTokenAddress;
address stableDebtTokenAddress;
address variableDebtTokenAddress;
address interestRateStrategyAddress;
uint128 accruedToTreasury;
uint128 unbacked;
uint128 isolationModeTotalDebt;
}
}
interface IPool {
function borrow(
address asset,
uint256 amount,
uint256 interestRateMode, // 1 for Stable, 2 for Variable
uint16 referralCode,
address onBehalfOf) external;
function supply(
address asset,
uint256 amount,
address onBehalfOf,
uint16 referralCode) external;
function withdraw(
address asset,
uint256 amount,
address to) external returns (uint256);
function getReserveData(
address asset) external view returns (DataTypes.ReserveData memory);
}
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address to, uint256 value) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 value) external returns (bool);
function transferFrom(address from, address to, uint256 value) external returns (bool);
}
contract AaveLender {
address public immutable AAVE_POOL_ADDRESS;
address public immutable STAKED_TOKEN_ADDRESS;
address public immutable ATOKEN_ADDRESS;
address public immutable OWNER;
mapping(address account => uint amount) public stakeByAccount;
uint public totalStake;
// Ejemplo en Scroll Sepolia
// Pool Address
// 0x48914C788295b5db23aF2b5F0B3BE775C4eA9440
// DAI
// 0x7984E363c38b590bB4CA35aEd5133Ef2c6619C40
// check at https://app.aave.com/
constructor(address aavePoolAddress, address stakedTokenAddress) {
AAVE_POOL_ADDRESS = aavePoolAddress;
STAKED_TOKEN_ADDRESS = stakedTokenAddress;
OWNER = msg.sender;
ATOKEN_ADDRESS = IPool(aavePoolAddress).getReserveData(stakedTokenAddress).aTokenAddress;
}
function stake(uint amount) public {
totalStake += amount;
stakeByAccount[msg.sender] += amount;
IERC20(STAKED_TOKEN_ADDRESS).transferFrom(msg.sender, address(this), amount);
IERC20(STAKED_TOKEN_ADDRESS).approve(AAVE_POOL_ADDRESS, amount);
IPool(AAVE_POOL_ADDRESS).supply(
STAKED_TOKEN_ADDRESS,
amount,
address(this),
0);
}
function unstake(uint amount) public {
require(amount <= stakeByAccount[msg.sender], "Not enough stake");
totalStake -= amount;
stakeByAccount[msg.sender] -= amount;
IPool(AAVE_POOL_ADDRESS).withdraw(
STAKED_TOKEN_ADDRESS,
amount,
msg.sender
);
}
function yieldEarned() public view returns(uint){
return IERC20(ATOKEN_ADDRESS).balanceOf(address(this)) - totalStake;
}
function withdraw(uint amount) public {
require(msg.sender == OWNER, "Sender is not owner");
require(amount <= yieldEarned(), "Maximum withdraw exceeded");
IPool(AAVE_POOL_ADDRESS).withdraw(
STAKED_TOKEN_ADDRESS,
amount,
msg.sender
);
}
}
//////////////////////////////////////////////////////////////////
//EAS
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import { IEAS, AttestationRequest, AttestationRequestData, RevocationRequest, RevocationRequestData } from "@ethereum-attestation-service/eas-contracts/contracts/IEAS.sol";
import { NO_EXPIRATION_TIME, EMPTY_UID } from "@ethereum-attestation-service/eas-contracts/contracts/Common.sol";
contract EASDemo
{
address easAddress = 0xaEF4103A04090071165F78D45D83A0C0782c2B2a;
bytes32 schema = 0x27d06e3659317e9a4f8154d1e849eb53d43d91fb4f219884d1684f86d797804a;
// check at https://scroll-sepolia.easscan.org/schema/view/0x27d06e3659317e9a4f8154d1e849eb53d43d91fb4f219884d1684f86d797804a
function sendIsFriend(address to, bool isFriend) public returns(bytes32)
{
return IEAS(easAddress).attest(
AttestationRequest({
schema: schema,
data: AttestationRequestData({
recipient: to,
expirationTime: NO_EXPIRATION_TIME,
revocable: false,
refUID: EMPTY_UID,
data: abi.encode(isFriend),
value: 0 // No value/ETH
})
})
);
}
}
@YandrielCod
Copy link

ACC:
// SPDX-License-Identifier: MIT
pragma solidity >=0.7.0 <0.9.0;

contract MultiSigWallet {
address[] public owners;
uint public requiredSignatures;

struct Transaction {
    address to;
    uint value;
    bytes data;
    bool executed;
    uint signatureCount;
}

mapping(uint => mapping(address => bool)) public signatures;
Transaction[] public transactions;
mapping(address => bool) public isOwner;

// Eventos
event OwnerAdded(address indexed owner);
event OwnerRemoved(address indexed owner);
event TransactionSubmitted(uint indexed txIndex, address indexed to, uint value);
event TransactionSigned(uint indexed txIndex, address indexed owner);
event TransactionExecuted(uint indexed txIndex);
event RequiredSignaturesUpdated(uint newRequiredSignatures);

modifier onlyOwner() {
    require(isOwner[msg.sender], "Not an owner");
    _;
}

modifier txExists(uint _txIndex) {
    require(_txIndex < transactions.length, "Transaction does not exist");
    _;
}

modifier notExecuted(uint _txIndex) {
    require(!transactions[_txIndex].executed, "Transaction already executed");
    _;
}

modifier notSigned(uint _txIndex) {
    require(!signatures[_txIndex][msg.sender], "Transaction already signed by this owner");
    _;
}

constructor(address[] memory _owners, uint _requiredSignatures) {
    require(_owners.length > 0, "Owners required");
    require(_requiredSignatures > 0 && _requiredSignatures <= _owners.length, "Invalid number of required signatures");

    for (uint i = 0; i < _owners.length; i++) {
        address owner = _owners[i];

        require(owner != address(0), "Invalid owner address");
        require(!isOwner[owner], "Owner not unique");

        isOwner[owner] = true;
        owners.push(owner);
        emit OwnerAdded(owner);
    }
    requiredSignatures = _requiredSignatures;
}

// Añadir un nuevo propietario
function addOwner(address newOwner) public onlyOwner {
    require(newOwner != address(0), "Invalid owner address");
    require(!isOwner[newOwner], "Owner already exists");

    isOwner[newOwner] = true;
    owners.push(newOwner);

    emit OwnerAdded(newOwner);
}

// Remover un propietario existente
function removeOwner(address owner) public onlyOwner {
    require(isOwner[owner], "Not an owner");

    // Requiere al menos el número mínimo de firmas si se quita un propietario
    require(owners.length - 1 >= requiredSignatures, "Cannot remove owner, not enough owners left");

    isOwner[owner] = false;

    for (uint i = 0; i < owners.length; i++) {
        if (owners[i] == owner) {
            owners[i] = owners[owners.length - 1];
            owners.pop();
            break;
        }
    }

    emit OwnerRemoved(owner);
}

// Actualizar el número de firmas requeridas
function updateRequiredSignatures(uint _newRequiredSignatures) public onlyOwner {
    require(_newRequiredSignatures > 0 && _newRequiredSignatures <= owners.length, "Invalid number of required signatures");
    requiredSignatures = _newRequiredSignatures;

    emit RequiredSignaturesUpdated(_newRequiredSignatures);
}

// Crear una nueva transacción
function submitTransaction(address _to, uint _value, bytes memory _data) public onlyOwner {
    uint txIndex = transactions.length;

    transactions.push(Transaction({
        to: _to,
        value: _value,
        data: _data,
        executed: false,
        signatureCount: 0
    }));

    emit TransactionSubmitted(txIndex, _to, _value);
}

// Firmar una transacción
function signTransaction(uint _txIndex) public onlyOwner txExists(_txIndex) notExecuted(_txIndex) notSigned(_txIndex) {
    Transaction storage transaction = transactions[_txIndex];
    transaction.signatureCount += 1;
    signatures[_txIndex][msg.sender] = true;

    emit TransactionSigned(_txIndex, msg.sender);

    // Ejecutar automáticamente si se alcanza el número requerido de firmas
    if (transaction.signatureCount >= requiredSignatures) {
        executeTransaction(_txIndex);
    }
}

// Ejecutar una transacción
function executeTransaction(uint _txIndex) public onlyOwner txExists(_txIndex) notExecuted(_txIndex) {
    Transaction storage transaction = transactions[_txIndex];

    // Verificación explícita de firmas suficientes
    require(transaction.signatureCount >= requiredSignatures, "Not enough signatures");

    transaction.executed = true;

    (bool success, ) = transaction.to.call{value: transaction.value}(transaction.data);
    require(success, "Transaction execution failed");

    emit TransactionExecuted(_txIndex);
}

// Obtener detalles de una transacción
function getTransaction(uint _txIndex) public view returns (address to, uint value, bytes memory data, bool executed, uint signatureCount) {
    Transaction storage transaction = transactions[_txIndex];
    return (transaction.to, transaction.value, transaction.data, transaction.executed, transaction.signatureCount);
}

// Función para recibir ETH
receive() external payable {}

}

@YandrielCod
Copy link

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment