#include <iostream>
#include <bits/stdc++.h> 
#include <string>

using namespace std;

typedef double db;
typedef long long ll;
typedef long double ld;
typedef vector<int> vi; 
typedef vector<ll> vl;
typedef vector<ld> vd;
typedef pair<int,int> pi;
typedef pair<ll,ll> pl;
typedef pair<ld,ld> pd;
typedef priority_queue<int> pqi;
typedef priority_queue<int, vi, greater<int>> mpqi;

#define IOS std::ios::sync_with_stdio(false); cin.tie(0);
#define F0R(i,a) for(int i = 0; i < a; i++)
#define R0F(i,a) for(int i = a - 1; i >= 0; i--)
#define pb push_back
#define mp make_pair
#define ins insert
#define ft front()
#define bk back()
#define f first
#define s second
#define trav(a,x) for(auto& a : x)
#define ALL(x) (x).begin(), (x).end()

const int MOD = 1000000007;
const int MX = 2e5+2;
const ll INF = 1000000000000000000;
const ld PI = 4*atan((ld)1);
const pi dir[4] = {{1,0}, {0,1}, {-1,0}, {0,-1}};

ll binExp(ll a1, ll b1, ll m1) { // a1^b1 mod m1
    a1 %= m1; ll res = 1;
    while (b1 > 0) {
        if (b1 & 1) res = res * a1 % m1;
        a1 = a1 * a1 % m1;
        b1 >>= 1;
    }
    return res;
}

bool isPrime(int ttttttt) {
    for (int d = 2; d * d <= ttttttt; d++) if (ttttttt % d == 0) return false;
    return true;
}

pair<vi,int> knapsack(vi val, vi weight, int cap) { 
	vi dp[size(val)+1]; dp[0].resize(cap+1); int totalVal = 0;
    F0R(i,size(val)) {
		dp[i+1] = dp[i];
        F0R(j,cap+1-weight[i]) dp[i+1][weight[i]+j] = max(dp[i+1][weight[i]+j],dp[i][j]+val[i]);
    }
    vi ans; R0F(i,size(val)) if (dp[i][cap] != dp[i+1][cap]) cap -= weight[i], totalVal += val[i], ans.pb(i);
    return mp(ans,totalVal);
}

bool ok(int val){
    return true;
}
int binSe(int l, int h){
    if(l == h - 1) return l;
    int mid = (l+h)/2;
    if(ok(mid)) return binSe(mid,h); return binSe(l,mid);
}

struct graph{
    int nodeCount;
    vector<pi> adj[MX];
    bool visit[MX];
    int dist[MX];
    void init(){
        F0R(i,nodeCount){
            visit[i] = false;
            dist[i] = MOD;
        }
    }
    void dfs(int node){
        visit[node] = true;
        trav(x,adj[node]){
            if(!visit[x.f]) dfs(x.f);
        }
    }
    void bfs(int startNode){
        queue<int> q;
        q.push(startNode);
        while(!q.empty()){
            // NEEDS IMPLEMENTATION
        }
    }
    void Dijkstra(){
        // NEEDS IMPLEMENTATION
    }
};

struct fenwick{
    int arrSize;
    ll arr[MX];
    ll tree[MX];
    void init(){
        F0R(i,arrSize) update(i+1,arr[i]);
    }
    ll query(int index1){
        ll sum = 0;
        while(index1 > 0){
            sum += tree[index1]; index1 -= index1 & (-index1);
        }
        return sum;
    }
    void update(int index1, ll val1){
        while(index1 <= arrSize){
            tree[index1] += val1; index1 += index1 & (-index1); 
        }
    }
};

// -----------

int n, m, a, b;
int c[3];

int main(){
    IOS;
    cin >> n >> m;
    F0R(i,3){
        c[i] = 0;
    }
    F0R(i,m){
        cin >> a >> b;
        a--;
        if(c[a] != 0 && c[a] != b){
            cout << -1; return 0;
        }
        c[a] = b;
    }
    bool zeroPlaced = false;
    F0R(i,n){
        if(c[i] == 0){
            if(zeroPlaced) cout << 0;
            else cout << 1;
        }
        else{
            cout << c[i];
        }
    }
    return 0;
    // You should actually read the notes to self.
}

/* NOTES TO SELF:
    Int overflow? Array bounds?
    Edge cases? (n = 1, n = 0)
    Don't be dumbosity please pace yourself.
*/