Sans titre

Gauthier BROS

on May 20, 2023

10:47 am

/**
*Submitted for verification at BscScan.com on 2023-04-18
*/

//SPDX-License-Identifier: Unlicense
pragma solidity 0.8.17;

abstract contract owned {
address payable public owner;
address public treasory;
address public oracle;
bool public paused;

modifier onlyOwner() {
    require(
        msg.sender == owner,
        "Only contract owner can call this function"
    );
    _;
}

modifier notPaused() {
    require(!paused, "Contract is paused");
    _;
}

function pause() public onlyOwner{
    paused = true;
}

function unpause() public onlyOwner {
    paused = false;
}

constructor() {
    owner = payable(msg.sender);
    treasory = 0x75e6ef3113266F7116B219f05Caede20889ddDf3;
    oracle = 0xd99884038A064466961bB0CE6e32646abD11bA9B;
}

function transferOwnership(address payable newOwner) public notPaused onlyOwner {
    owner = newOwner;
}

function transferTreasoryOwnership(address payable newTreasory)
    public
    notPaused
    onlyOwner
{
    treasory = newTreasory;
}

}

interface IBEP20 {
function transfer(address _to, uint256 _value) external returns (bool);

function transferFrom(
    address _from,
    address _to,
    uint256 _value
) external returns (bool);

function balanceOf(address _owner) external view returns (uint256);

}

abstract contract ERC20Holder is owned {
mapping(address => bool) public acceptedTokens;

function modToken(address token, bool accepted) public notPaused onlyOwner {
    acceptedTokens[token] = accepted;
}

receive() external payable {
    // Accept all incoming tokens
}

// a function to receive BEP20 tokens
function receiveToken(address token, uint256 amount) public notPaused {
    require(acceptedTokens[token], "Token not accepted");
    require(
        IBEP20(token).transferFrom(msg.sender, address(this), amount),
        "Transfer failed"
    );
}

}

contract oracleClient is ERC20Holder {
function setOracle(address a) public notPaused onlyOwner {
oracle = a;
}
}

interface IOracle {
function ask(
uint8 typeSN,
string calldata idPost,
string calldata idUser,
bytes32 idRequest
) external;

function askBounty(
    uint8 typeSN,
    string calldata idPost,
    string calldata idUser,
    bytes32 idProm
) external;

}

contract campaign is oracleClient {

struct cpRatio {
    uint256 likeRatio;
    uint256 shareRatio;
    uint256 viewRatio;
    uint256 reachLimit;
}

struct bountyUnit {
    uint256 minRange;
    uint256 maxRange;
    uint256 typeSN;
    uint256 amount;
}

struct Campaign {
    address advertiser;
    string dataUrl;
    uint64 startDate;
    uint64 endDate;
    uint64 nbProms;
    uint64 nbValidProms;
    mapping(uint64 => bytes32) proms;
    Fund funds;
    mapping(uint8 => cpRatio) ratios;
    bountyUnit[] bounties;
}

struct Fund {
    address token;
    uint256 amount;
}

struct Result {
    bytes32 idProm;
    uint64 likes;
    uint64 shares;
    uint64 views;
}

struct promElement {
    address influencer;
    bytes32 idCampaign;
    bool isAccepted;
    bool isPayed;
    Fund funds;
    uint8 typeSN;
    uint256 appliedDate;
    uint64 abosNumber;
    string idPost;
    string idUser;
    uint64 nbResults;
    mapping(uint64 => bytes32) results;
    bytes32 prevResult;
    uint256 lastHarvest;
    uint256 validate;
}

mapping(bytes32 => Campaign) public campaigns;
mapping(bytes32 => promElement) public proms;
mapping(bytes32 => Result) public results;
mapping(bytes32 => bool) public isAlreadyUsed;

event CampaignCreated(
    bytes32 indexed id,
    uint64 startDate,
    uint64 endDate,
    string dataUrl
);
event CampaignFundsSpent(bytes32 indexed id);
event CampaignApplied(bytes32 indexed id, bytes32 indexed prom);
event PromAccepted(bytes32 indexed id);
event PromPayed(bytes32 indexed id, uint256 amount);
event CampaignFunded(bytes32 indexed id, uint256 amount);

function priceRatioCampaign(
    bytes32 idCampaign,
    uint8 typeSN,
    uint256 likeRatio,
    uint256 shareRatio,
    uint256 viewRatio,
    uint256 limit
) internal notPaused {
    require(
        campaigns[idCampaign].advertiser == msg.sender,
        "campaign owner mismatch"
    );
    campaigns[idCampaign].ratios[typeSN] = cpRatio(
        likeRatio,
        shareRatio,
        viewRatio,
        limit
    );
}

function fundCampaign(
    bytes32 idCampaign,
    address token,
    uint256 amount
) public notPaused {
    require(
        campaigns[idCampaign].endDate > block.timestamp,
        "campaign ended"
    );
    require(
        campaigns[idCampaign].funds.token == address(0) ||
            campaigns[idCampaign].funds.token == token,
        "token mismatch"
    );

    IBEP20 erc20 = IBEP20(token);
    uint256 prev_amount = campaigns[idCampaign].funds.amount;
    uint256 added_amount;
    uint256 trisory_amount;

    if (token == 0x448BEE2d93Be708b54eE6353A7CC35C4933F1156) {
        added_amount = (amount * 95) / 100;
        trisory_amount = amount - added_amount;
    } else {
        added_amount = (amount * 85) / 100;
        trisory_amount = amount - added_amount;
    }

    erc20.transferFrom(msg.sender, treasory, trisory_amount);
    erc20.transferFrom(msg.sender, address(this), added_amount);

    campaigns[idCampaign].funds = Fund(token, added_amount + prev_amount);
    emit CampaignFunded(idCampaign, added_amount);
}

function createPriceFundAll(
    string memory dataUrl,
    uint64 startDate,
    uint64 endDate,
    uint256[] memory ratios,
    address token,
    uint256 amount
) public notPaused returns (bytes32 idCampaign) {
    require(endDate > block.timestamp, "end date too early");
    require(endDate > startDate, "end date early than start");

    bytes32 campaignId = keccak256(
        abi.encodePacked(
            msg.sender,
            dataUrl,
            startDate,
            endDate,
            block.timestamp
        )
    );
    Campaign storage c = campaigns[campaignId];
    c.advertiser = msg.sender;
    c.dataUrl = dataUrl;
    c.startDate = startDate;
    c.endDate = endDate;
    c.nbProms = 0;
    c.nbValidProms = 0;
    c.funds = Fund(address(0), 0);
    //campaigns[campaignId] = Campaign(msg.sender,dataUrl,startDate,endDate,0,0,Fund(address(0),0));
    emit CampaignCreated(campaignId, startDate, endDate, dataUrl);

    for (uint8 i = 0; i < ratios.length; i = i + 4) {
        priceRatioCampaign(
            campaignId,
            (i / 4) + 1,
            ratios[i],
            ratios[i + 1],
            ratios[i + 2],
            ratios[i + 3]
        );
    }

    fundCampaign(campaignId, token, amount);
    return campaignId;
}

function createPriceFundBounty(
    string memory dataUrl,
    uint64 startDate,
    uint64 endDate,
    uint256[] memory bounties,
    address token,
    uint256 amount
) public notPaused returns (bytes32 idCampaign) {
    require(endDate > block.timestamp, "end date too early");
    require(endDate > startDate, "end date early than start");

    bytes32 campaignId = keccak256(
        abi.encodePacked(
            msg.sender,
            dataUrl,
            startDate,
            endDate,
            block.timestamp
        )
    );
    Campaign storage c = campaigns[campaignId];
    c.advertiser = msg.sender;
    c.dataUrl = dataUrl;
    c.startDate = startDate;
    c.endDate = endDate;
    c.nbProms = 0;
    c.nbValidProms = 0;
    c.funds = Fund(address(0), 0);
    for (uint256 i = 0; i < bounties.length; i = i + 4) {
        c.bounties.push(
            bountyUnit(
                bounties[i],
                bounties[i + 1],
                bounties[i + 2],
                bounties[i + 3]
            )
        );
    }

    emit CampaignCreated(campaignId, startDate, endDate, dataUrl);

    fundCampaign(campaignId, token, amount);
    return campaignId;
}

function VerifyMessage(
    bytes32 _hashedMessage,
    uint8 _v,
    bytes32 _r,
    bytes32 _s
) public notPaused view  returns (address) {
    //bytes memory prefix = "\x19Ethereum Signed Message:\n32";
    //bytes32 prefixedHashMessage = keccak256(abi.encodePacked(prefix, _hashedMessage));

    address signer = ecrecover(_hashedMessage, _v, _r, _s);
    return signer;
}

function validateProm(
    bytes32 idCampaign,
    uint8 typeSN,
    string memory idPost,
    string memory idUser,
    uint64 abosNumber,
    address ownerLink,
    bytes32 _hashedMessage,
    uint8 _v,
    bytes32 _r,
    bytes32 _s
) public notPaused {
    Campaign storage cmp = campaigns[idCampaign];
    require(cmp.endDate > block.timestamp, "campaign ended");
    address signer = VerifyMessage(_hashedMessage, _v, _r, _s);
    require(signer == ownerLink, "campaign applayer is mismatch");
    bytes32 prom = keccak256(
        abi.encodePacked(
            idCampaign,
            typeSN,
            idPost,
            idUser,
            ownerLink,
            block.timestamp
        )
    );
    require(!isAlreadyUsed[prom], "link already sent");
    promElement storage p = proms[prom];
    p.influencer = ownerLink;
    p.idCampaign = idCampaign;
    p.isAccepted = true;
    p.funds = Fund(address(0), 0);
    p.typeSN = typeSN;
    p.idPost = idPost;
    p.idUser = idUser;
    p.abosNumber = abosNumber;
    p.nbResults = 0;
    p.prevResult = 0;
    p.validate = block.timestamp;
    cmp.nbValidProms++;

    emit PromAccepted(prom);
}

function updateCampaignStats(bytes32 idCampaign) public notPaused {
    for (uint64 i = 0; i < campaigns[idCampaign].nbProms; i++) {
        bytes32 idProm = campaigns[idCampaign].proms[i];
        if (proms[idProm].isAccepted) {
            bytes32 idRequest = keccak256(
                abi.encodePacked(
                    proms[idProm].typeSN,
                    proms[idProm].idPost,
                    proms[idProm].idUser,
                    block.timestamp
                )
            );
            results[idRequest] = Result(idProm, 0, 0, 0);
            proms[idProm].results[proms[idProm].nbResults++] = idRequest;
            ask(
                proms[idProm].typeSN,
                proms[idProm].idPost,
                proms[idProm].idUser,
                idRequest
            );
        }
    }
}

function updatePromStats(bytes32 idProm)
    public
    notPaused
    returns (bytes32 requestId)
{
    require(proms[idProm].isAccepted, "link not validated");
    bytes32 idRequest = keccak256(
        abi.encodePacked(
            proms[idProm].typeSN,
            proms[idProm].idPost,
            proms[idProm].idUser,
            block.timestamp
        )
    );
    results[idRequest] = Result(idProm, 0, 0, 0);
    proms[idProm].results[proms[idProm].nbResults++] = idRequest;
    ask(
        proms[idProm].typeSN,
        proms[idProm].idPost,
        proms[idProm].idUser,
        idRequest
    );
    return idRequest;
}

function updateBounty(bytes32 idProm) public notPaused {
    require(proms[idProm].isAccepted, "link not validated");
    askBounty(
        proms[idProm].typeSN,
        proms[idProm].idPost,
        proms[idProm].idUser,
        idProm
    );
}

function ask(
    uint8 typeSN,
    string memory idPost,
    string memory idUser,
    bytes32 idRequest
) public notPaused {
    IOracle o = IOracle(oracle);
    o.ask(typeSN, idPost, idUser, idRequest);
}

function askBounty(
    uint8 typeSN,
    string memory idPost,
    string memory idUser,
    bytes32 idProm
) public notPaused {
    IOracle o = IOracle(oracle);
    o.askBounty(typeSN, idPost, idUser, idProm);
}

function updateBounty(bytes32 idProm, uint256 nbAbos)
    external notPaused
    returns (bool ok)
{
    require(msg.sender == oracle, "oracle mismatch");

    promElement storage prom = proms[idProm];
    require(!prom.isPayed, "link already paid");
    prom.isPayed = true;
    prom.funds.token = campaigns[prom.idCampaign].funds.token;

    uint256 gain = 0;
    for (
        uint256 i = 0;
        i < campaigns[prom.idCampaign].bounties.length;
        i++
    ) {
        if (
            nbAbos >= campaigns[prom.idCampaign].bounties[i].minRange &&
            nbAbos < campaigns[prom.idCampaign].bounties[i].maxRange &&
            prom.typeSN == campaigns[prom.idCampaign].bounties[i].typeSN
        ) {
            gain = campaigns[prom.idCampaign].bounties[i].amount;
        }
    }

    if (campaigns[prom.idCampaign].funds.amount <= gain) {
        //campaigns[prom.idCampaign].endDate = uint64(block.timestamp);
        prom.funds.amount += campaigns[prom.idCampaign].funds.amount;
        campaigns[prom.idCampaign].funds.amount = 0;
        emit CampaignFundsSpent(prom.idCampaign);
        return true;
    }
    campaigns[prom.idCampaign].funds.amount -= gain;
    prom.funds.amount += gain;
    return true;
}

function update(
    bytes32 idRequest,
    uint64 likes,
    uint64 shares,
    uint64 views
) external notPaused returns (bool ok) {
    require(msg.sender == oracle, "oracle mismatch");

    promElement storage prom = proms[results[idRequest].idProm];

    results[idRequest].likes = likes;
    results[idRequest].shares = shares;
    results[idRequest].views = views;

    uint256 gain = 0;

    if (likes > results[prom.prevResult].likes)
        gain +=
            (likes - results[prom.prevResult].likes) *
            campaigns[prom.idCampaign].ratios[prom.typeSN].likeRatio;
    if (shares > results[prom.prevResult].shares)
        gain +=
            (shares - results[prom.prevResult].shares) *
            campaigns[prom.idCampaign].ratios[prom.typeSN].shareRatio;
    if (views > results[prom.prevResult].views)
        gain +=
            (views - results[prom.prevResult].views) *
            campaigns[prom.idCampaign].ratios[prom.typeSN].viewRatio;
    prom.prevResult = idRequest;

    //
    // warn campaign low credits
    //

    if (prom.funds.token == address(0)) {
        prom.funds.token = campaigns[prom.idCampaign].funds.token;
    }
    if (campaigns[prom.idCampaign].funds.amount <= gain) {
        //campaigns[prom.idCampaign].endDate = uint64(block.timestamp);
        prom.funds.amount += campaigns[prom.idCampaign].funds.amount;
        campaigns[prom.idCampaign].funds.amount = 0;
        emit CampaignFundsSpent(prom.idCampaign);
        return true;
    }
    campaigns[prom.idCampaign].funds.amount -= gain;
    prom.funds.amount += gain;
    return true;
}

function getGains(bytes32 idProm) public notPaused {
    require(proms[idProm].influencer == msg.sender, "link owner mismatch");
    uint256 diff = block.timestamp - proms[idProm].appliedDate;
    require(diff > 86400, "less than 24h");

    require(
        block.timestamp - proms[idProm].lastHarvest > 86400,
        "less than 24h to harvest again"
    );

    IBEP20 erc20 = IBEP20(proms[idProm].funds.token);
    uint256 amount = proms[idProm].funds.amount;
    proms[idProm].funds.amount = 0;
    proms[idProm].lastHarvest = block.timestamp;
    erc20.transfer(proms[idProm].influencer, amount);

    emit PromPayed(idProm, amount);
}

function getRemainingFunds(bytes32 idCampaign) public notPaused {
    require(
        campaigns[idCampaign].advertiser == msg.sender,
        "campaign owner mismatch"
    );
    require(
        campaigns[idCampaign].endDate < block.timestamp,
        "campaign not ended"
    );
    require(
        block.timestamp - campaigns[idCampaign].endDate > 1296000,
        "Withdraw not allowed under 15 days"
    );

    IBEP20 erc20 = IBEP20(campaigns[idCampaign].funds.token);
    uint256 amount = campaigns[idCampaign].funds.amount;
    campaigns[idCampaign].funds.amount = 0;
    erc20.transfer(campaigns[idCampaign].advertiser, amount);
}

function getProms(bytes32 idCampaign)
    public notPaused
    view
    returns (bytes32[] memory cproms)
{
    uint256 nbProms = campaigns[idCampaign].nbProms;
    cproms = new bytes32[](nbProms);

    for (uint64 i = 0; i < nbProms; i++) {
        cproms[i] = campaigns[idCampaign].proms[i];
    }
    return cproms;
}

function getRatios(bytes32 idCampaign)
    public notPaused
    view
    returns (
        uint8[] memory types,
        uint256[] memory likeRatios,
        uint256[] memory shareRatios,
        uint256[] memory viewRatios,
        uint256[] memory limits
    )
{
    uint8 l = 10;
    types = new uint8[](l);
    likeRatios = new uint256[](l);
    shareRatios = new uint256[](l);
    viewRatios = new uint256[](l);
    limits = new uint256[](l);
    for (uint8 i = 0; i < l; i++) {
        types[i] = i + 1;
        likeRatios[i] = campaigns[idCampaign].ratios[i + 1].likeRatio;
        shareRatios[i] = campaigns[idCampaign].ratios[i + 1].shareRatio;
        viewRatios[i] = campaigns[idCampaign].ratios[i + 1].viewRatio;
        limits[i] = campaigns[idCampaign].ratios[i + 1].reachLimit;
    }
    return (types, likeRatios, shareRatios, viewRatios, limits);
}

function getBounties(bytes32 idCampaign)
    public notPaused
    view
    returns (uint256[] memory bounty)
{
    bounty = new uint256[](campaigns[idCampaign].bounties.length * 4);
    for (uint8 i = 0; i < campaigns[idCampaign].bounties.length; i++) {
        bounty[i * 4] = campaigns[idCampaign].bounties[i].minRange;
        bounty[i * 4 + 1] = campaigns[idCampaign].bounties[i].maxRange;
        bounty[i * 4 + 2] = campaigns[idCampaign].bounties[i].typeSN;
        bounty[i * 4 + 3] = campaigns[idCampaign].bounties[i].amount;
    }
    return bounty;
}

function getResults(bytes32 idProm)
    public notPaused
    view
    returns (bytes32[] memory creq)
{
    uint256 nbResults = proms[idProm].nbResults;
    creq = new bytes32[](nbResults);
    for (uint64 i = 0; i < nbResults; i++) {
        creq[i] = proms[idProm].results[i];
    }
    return creq;
}

function getIsUsed(
    bytes32 idCampaign,
    uint8 typeSN,
    string memory idPost,
    string memory idUser
) public notPaused view returns (bool) {
    bytes32 prom = keccak256(
        abi.encodePacked(idCampaign, typeSN, idPost, idUser)
    );
    return isAlreadyUsed[prom];
}

}

Related posts 

  • Navigating the Blockchain Landscape: An Introduction for Beginners

    Bruno BROS

    June 1, 2023

    Explore the world of blockchain with our comprehensive guide. Understand what blockchain is, how it works, its potential applications, and the challenges it faces. Gain insights into the future of this transformative technology and its impact on various industries. Eos rerum ipsa qui repellendus quaerat ea magni voluptas ut vitae consequuntur et distinctio ipsa! Aut aliquid error vel Quis quibusdam aut modi voluptatibus non ullam rerum vel exercitationem necessitatibus. Et autem minus et beatae corrupti in eligendi modi ea similique repellat sit repellat corporis et reiciendis maiores 33 soluta officiis! Qui sint nesciunt ea maiores consequuntur quo dolorum earum aut veniam deleniti sit sint quae ab voluptatem dolores quo exercitationem molestiae.

  • A Journey from Facebook Applications to Blockchain Innovation

    Gauthier BROS

    May 9, 2023

    Hello everyone and welcome to my blog. I’m Gauthier Bros, a passionate entrepreneur and developer who’s been working with Facebook applications since 2010, and notably created the first “live streaming” solution on Facebook during the same year. I am the creator of numerous solutions such as contact form, newsletter, store, and iframe apps, which are used by a large number of users and brands worldwide. In 2017, I transitioned from Facebook applications to Ethereum smart-contracts, putting the experience of my company, Atayen, to good use in service of the blockchain. My goal? To democratize blockchain technology. In pursuit of this goal, I launched SaTT, the 3.0 wallet, designed to make storing and sending cryptocurrencies as easy as sending an email. The Smart Advertising Transaction Token (SaTT) is a utility token that allows advertisers to buy smart advertising services on the SaTT ethereum-based dApp. All transactions between advertisers and influencers/publishers are governed by the SaTT smart contract which automatically ensures speed, transparency, security, and cost-efficiency【9†source】. This innovative approach to advertising helps address industry challenges such as the lack of transparency in the supply chain, payment delays, and more. We have developed blockchain oracles that fetch data from third-party APIs of social media platforms like YouTube, Facebook, Twitter, Instagram, and others. Actions such as likes, shares, views, and tweets can then be evaluated to help quantify the return on investment (ROI), a significant concern for advertisers and marketers【9†source】. Our minimum viable product (MVP) is already online, allowing advertisers and marketers to list their advertising campaigns on the SaTT platform, specify the number of tokens available for their campaign, and allocate tokens according to which social media platforms they wish to be promoted on. In addition, influencers (or micro-influencers) can participate in campaigns by publishing on social networks and are remunerated according to the performance of their posts【10†source】. What sets us apart from other marketing projects like aqilliZ, Brave, or normal aggregators like Addragon and Coinzilla, is our focus on a working smart advertising solution built on the Ethereum blockchain, unlike aqilliZ which is built on the Zilliqa blockchain. We’re also distinct from Brave, which is a web browser that values attention and content creators, rewarding users with the Basic Attention Token (BAT). Addragon and Coinzilla, on the other hand, are more about media buys and ad placements, like banners and advertisements【11†source】. Our successful ICO, where we raised $7 million, was largely due to our emphasis on having a working platform. Amid the ICO hype in late 2017 and part of 2018, many projects touted blockchain solutions but failed to deliver a working product. This left investors wary of blockchain projects because hype alone cannot sustain a project’s continued success. Our team, coming from Atayen, Inc, already provided technology solutions such as our Facebook pages for business apps, so we understand what it takes to deliver these kinds of solutions【12†source】. We chose to use the Ethereum blockchain because it is the leader in smart contract protocols, considering the massive number of projects that have adopted it. Despite the high gas fees, we are still confident in our choice, especially considering the upcoming Ethereum 2.0【13†source】.Looking to the future, I’m committed to advancing the adoption and democratization of blockchain technology. Although blockchain is still in its early stages, the crypto community is rapidly expanding and bringing together people from different backgrounds. This innovative technology has a lot more to offer, and you can count on our local talents to exploit and develop it in France and internationally.

Comments

or 

Login

 to comment

Unleashing Potential: Pioneering the Digital Frontier with Expert Guidance

Paid access

  • One shot payment for online meetings
  • Subscriptions

Payments

Payments with credit card

Contact Gauthier

gauthier@bros.ai

Contact form

bros.ai

Follow Gauthier on social media

Copyright ©

2023

bros.ai, tous droits réservés.

Propulsé par GBB Corp.